import CalcClass.CalcBaseVisitor;
import CalcClass.CalcParser;
import baseClass.*;
import checkClass.*;
import errorHandle.ErrorDeliver;
import intermediateCodeClass.MidCode;
import intermediateCodeClass.MidCodeNode;
import intermediateCodeClass.OperationEnum;
import intermediateCodeClass.ParaGenerate;
import log4Compile.Log;
import org.antlr.v4.runtime.Token;
import symbolClass.FunctionNode;
import symbolClass.ParaMap;
import symbolClass.SymbolNode;
import symbolClass.TypeDeclaNode;

import java.util.*;

/*
    自己的访问器
    2022-3-12-杨海南
 */

public class SelfVisitor extends CalcBaseVisitor {

    //类型检查器
    private final TypeCheck typeCheck = TypeCheck.getTypeCheckInstance();
    //语义错误记录
    private final ErrorDeliver errorDeliver = ErrorDeliver.getErrorDeliverInstance();
    //符号表（包含函数/过程）
    private final ParaMap paraMap = ParaMap.getParaMapInstance();

//    private final Stack<TypeExpression> typeExpressionStack = new Stack<>();

//    private final Stack<TypeExpression> expressionListStack = new Stack<>();

    private final Log log = Log.getLogInstance();
    private final ParaGenerate paraGenerate = ParaGenerate.getInstance();
    private final MidCode midCode = MidCode.getInstance();
    //表示当前是否在创建record中
    //如果在创建的话，则在遇到变量声明的时候不需要插入符号表
//    private boolean recordRead = false;
    private boolean periodRead = false;
    // 用来在声明数组时存储值
    private final Stack<Object> periodStack = new Stack<>();
    // 保存函数名，区分函数和过程
    private final Stack<String> funcNameStack = new Stack<>();
    // 保存函数的返回值，递归调用时使用
    private final Stack<TypeExpression> returnTypeStack = new Stack<>();
    // 用来表示是不是在赋值语句中充当左值
    private boolean isLeftValue = false;
    // 最主要的，负责多个
    private final Stack<Object> expressionStack = new Stack<>();
    private final LinkedList<MidCodeNode> caseNodeList = new LinkedList<>();
    private final LinkedList<Object> branchConstList = new LinkedList<>();
    private final Stack<Object> caseExpStack = new Stack<>();
    //    private final Stack<Integer> recordSizeStack = new Stack<>();
    private final Stack<ArrayRange> periodRangeStack = new Stack<>();
    //这个地方是存类型声明时各个字段的名称-type名
    private final Stack<HashMap<String, String>> recordVarListMap = new Stack<>();
    //存声明类型时字段名称-大小
    private final Stack<HashMap<String, Integer>> recordVarSizeMap = new Stack<>();
    //存储type声明时的type占据内存的大小，用于内存对齐
    private final Stack<Integer> typeSizeStack = new Stack<>();

    //负责传递参数使用
    private final Stack<ParaTrans> paraTransStack = new Stack<>();
    //负责传递参数的类型
//    private final Stack<String> paraTypeTransStack = new Stack<>();
    //负责数组或域的获取
    private final LinkedList<VarListAccess> idVarQueue = new LinkedList<>();
    //表达式列表，负责在variable中嵌套访问以及call函数
    private final LinkedList<String> expressionQueue = new LinkedList<>();

    @Override
    public Object visitS(CalcParser.SContext ctx) {
        return super.visitS(ctx);
    }

    /*
        整个程序起始
        语法：program_head program_body
     */
    @Override
    public Object visitProgramStart(CalcParser.ProgramStartContext ctx) {
        log.logger("进入visitProgramStart方法", 1);
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROGRAM_START));
        //定向，创建一个新的‘块’到Map中
        paraMap.location();
        TypeExpression headType = (TypeExpression) visit(ctx.program_head());
        TypeExpression bodyType = (TypeExpression) visit(ctx.program_body());
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROGRAM_BODY_END));
        //重定向,移除栈顶‘块’，这里表示程序的结束，所有的符号表都被清空了
        paraMap.relocation();
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROGRAM_END));
        log.logger("退出visitProgramStart方法", 1);
        if (headType.typeEquals(ToolTypeEnum.ERROR) || bodyType.typeEquals(ToolTypeEnum.ERROR)) {
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        程序声明（程序头）
        有参数表
        语法：PROGRAM ID LEFT_BRA identifier_list RIGHT_BRA SEMICOLON
        在这里要声明一个程序
        初始化一个segment作为最基本的
     */
    @Override
    public TypeExpression visitProgramHead(CalcParser.ProgramHeadContext ctx) {
        log.logger("进入visitProgramHead方法", 1);
        String programName = ctx.ID().getText();
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_START, programName));
        // 初始化程序
        LinkedList<String> idList = (LinkedList<String>) visit(ctx.identifier_list());
        paraMap.putFunction(programName, new FunctionNode(programName, null, idList.size(), null, null));
        for (String idName : idList) {
            if (paraMap.containsSymbol(idName)) {
                paraMap.putVariable(idName, new SymbolNode(idName, null, false, 0));
                //加入参数的声明，不知道这参数有什么用
                midCode.addNewCode(new MidCodeNode(OperationEnum.PARAM, false, null, idName));
            } else {
                // 错误流，重名参数
                int line = ctx.ID().getSymbol().getLine();
                int inLine = ctx.getText().indexOf(idName);
                String tips = "变量：'" + idName + "' 重复定义";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
            }
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_END, programName));
        log.logger("退出visitProgramHead方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        程序体
        包含很多东西，当然很多东西也是可有可无
        需要检测是否存在这些语句
        const_declarations?
        type_declarations?
        var_declarations?
        subprogram_declarations?
        compound_statement
        如果存在的话则需要去依次分析
     */
    @Override
    public TypeExpression visitProgramBody(CalcParser.ProgramBodyContext ctx) {
        log.logger("进入visitProgramBody方法", 1);
        //如果常量声明部分存在的话就去访问
        TypeExpression resultType = null;
        TypeExpression bodyType;
        if (ctx.const_declarations() != null) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.CONST_START));
            bodyType = (TypeExpression) visit(ctx.const_declarations());
            midCode.addNewCode(new MidCodeNode(OperationEnum.CONST_END));
            if (bodyType.typeEquals(ToolTypeEnum.ERROR)) {
                resultType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        }
        if (ctx.type_declarations() != null) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.TYPE_START));
            bodyType = (TypeExpression) visit(ctx.type_declarations());
            midCode.addNewCode(new MidCodeNode(OperationEnum.TYPE_END));
            if (bodyType.typeEquals(ToolTypeEnum.ERROR)) {
                resultType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        }
        if (ctx.var_declarations() != null) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.VAR_START));
            bodyType = (TypeExpression) visit(ctx.var_declarations());
            midCode.addNewCode(new MidCodeNode(OperationEnum.VAR_END));
            if (bodyType.typeEquals(ToolTypeEnum.ERROR)) {
                resultType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        }
        if (ctx.subprogram_declarations() != null) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.SUB_PROGRAM_START));
            bodyType = (TypeExpression) visit(ctx.subprogram_declarations());
            midCode.addNewCode(new MidCodeNode(OperationEnum.SUB_PROGRAM_END));
            if (bodyType.typeEquals(ToolTypeEnum.ERROR)) {
                resultType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROGRAM_BODY_START));
        bodyType = (TypeExpression) visit(ctx.compound_statement());
        if (bodyType.typeEquals(ToolTypeEnum.ERROR)) {
            resultType = new TypeExpression(ToolTypeEnum.ERROR);
        }
        if (resultType == null)
            resultType = new TypeExpression(ToolTypeEnum.VOID);
        log.logger("退出visitProgramBody方法", 1);
        return resultType;
    }

    /*
        多个参数的参数表，逗号分隔
        语法：identifier_list COMMA ID
     */
    @Override
    public LinkedList<String> visitMultiIdentifier(CalcParser.MultiIdentifierContext ctx) {
        log.logger("进入visitMultiIdentifier方法", 1);
        LinkedList<String> innerList = (LinkedList<String>) visit(ctx.identifier_list());
        String lineString = ctx.getText();
        String newVarName = (String) visit(ctx.ID());
        for (String old : innerList) {
            if (old.equals(newVarName)) {
                // 报错，重复定义变量
                int line = ctx.ID().getSymbol().getLine();
                int inLine = lineString.indexOf(old);
                String tips = "变量：'" + old + "'重复定义";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
                log.logger("退出visitMultiIdentifier方法", 1);
                return innerList;
            }
        }
        innerList.add(ctx.ID().getText());
        log.logger("退出visitMultiIdentifier方法", 1);
        return innerList;
    }

    /*
        单个参数表
        语法：ID
     */
    @Override
    public LinkedList<String> visitSigIdentifier(CalcParser.SigIdentifierContext ctx) {
        log.logger("进入visitSigIdentifier方法", 1);
        String paraName = ctx.ID().getText();
        LinkedList<String> idNameList = new LinkedList<>();
        idNameList.add(paraName);
        log.logger("退出visitSigIdentifier方法", 1);
        return idNameList;
    }

    /*
        常量的声明，全局？
        一个程序只有这一个常量声明的地方
        所以会有好几条
        语法：CONST const_declaration SEMICOLON
     */
    @Override
    public TypeExpression visitConstDecla(CalcParser.ConstDeclaContext ctx) {
        //去遍历常数声明
        log.logger("进入visitConstDecla方法", 1);
        TypeExpression constType = (TypeExpression) visit(ctx.const_declaration());
        log.logger("退出visitConstDecla方法", 1);
        return constType;

    }


    /*
        给多个标识符赋值（不同的值）
        语法：const_declaration SEMICOLON ID EQUAL const_variable
        注意是用等号赋值的，分号分隔
     */
    @Override
    public TypeExpression visitMultiConstExt(CalcParser.MultiConstExtContext ctx) {
        log.logger("进入visitMultiConstExt方法", 1);
        //  多个常量赋值
        TypeExpression innerType = (TypeExpression) visit(ctx.const_declaration());
        String constId = ctx.ID().getText();
        if (paraMap.topContainsSymbol(constId)) {
            // 错误流
            redefineID(ctx.ID().getSymbol());
            log.logger("退出visitMultiConstExt方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        TypeExpression type = (TypeExpression) visit(ctx.const_variable());
        Object constObj = expressionStack.pop();
        midCode.addNewCode(new MidCodeNode(OperationEnum.CONST, constObj, constId));
        //给这个常量在符号表中注册
        SymbolNode constNode = new SymbolNode(constId, type, true, 0);
        paraMap.putVariable(constId, constNode);

        if (innerType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitMultiConstExt方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitMultiConstExt方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        给标识符赋值（常量）
        语法：ID EQUAL const_variable
     */
    @Override
    public TypeExpression visitSigConstExt(CalcParser.SigConstExtContext ctx) {
        log.logger("进入visitSigConstExt方法", 1);
        String constId = ctx.ID().getText();
        if (paraMap.topContainsSymbol(constId)) {
            // 记录重复声明的错误
            redefineID(ctx.ID().getSymbol());
            log.logger("退出visitSigConstExt方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        TypeExpression type = (TypeExpression) visit(ctx.const_variable());
        Object constObj = expressionStack.pop();
        midCode.addNewCode(new MidCodeNode(OperationEnum.CONST, constObj, constId));
        //给这个常量在符号表中注册
        SymbolNode constNode = new SymbolNode(constId, type, true, 0);
        paraMap.putVariable(constId, constNode);
        log.logger("退出visitSigConstExt方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        正的变量做常量：ADD ID
     */
    @Override
    public TypeExpression visitAddID(CalcParser.AddIDContext ctx) {
        log.logger("进入visitAddID方法", 1);
        String plusId = ctx.ID().getText();
        // 变量的类型，因为是已经定义的变量，所以可以在符号表中查到这个变量的变量类型，当变量名存在时直接查询即可
        TypeExpression idSymbol;
        if (paraMap.containsVariable(plusId)) {
            // 正如此处，直接查询变量的类型
            idSymbol = paraMap.getVariable(plusId).getSymbolType();
            // 然后在这里做变量的类型检查，因为可以做加减运算，所以必须是整数或者实数类型
            if (idSymbol.typeEquals(BaseTypeEnum.INTEGER) || idSymbol.typeEquals(BaseTypeEnum.REAL)) {
                expressionStack.push(plusId);
                log.logger("退出visitAddID方法", 1);
                return idSymbol;
            } else {
                // 其他情况都是类型不符合，添加到错误流中即可
                int line = ctx.ID().getSymbol().getLine();
                int inLine = ctx.ID().getSymbol().getCharPositionInLine();
                String tips = "变量:'" + plusId + "'类型不符合，需为整数或实数类型";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                log.logger("退出visitSubID方法", 1);
                return new TypeExpression(ToolTypeEnum.ERROR);
            }
        } else {
            // 这个地方是没找到这个变量，添加到错误流中
            redefineID(ctx.ID().getSymbol());
            log.logger("退出visitAddID方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        负的变量做常量：SUB ID，类似ADD ID
     */
    @Override
    public TypeExpression visitSubID(CalcParser.SubIDContext ctx) {
        log.logger("进入visitSubID方法", 1);
        String subId = ctx.ID().getText();
        TypeExpression idSymbol;
        if (paraMap.containsVariable(subId)) {
            idSymbol = paraMap.getVariable(subId).getSymbolType();
            if (idSymbol.typeEquals(BaseTypeEnum.INTEGER) || idSymbol.typeEquals(BaseTypeEnum.REAL)) {
                expressionStack.push("-" + subId);
                log.logger("退出visitSubID方法", 1);
                return idSymbol;
            } else {
                int line = ctx.ID().getSymbol().getLine();
                int inLine = ctx.ID().getSymbol().getCharPositionInLine();
                String tips = "变量:'" + subId + "'类型不符合，需为整数或实数类型";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                log.logger("退出visitSubID方法", 1);
                return new TypeExpression(ToolTypeEnum.ERROR);
            }
        } else {
            // 添加到错误流中
            undefineID(ctx.ID().getSymbol());
            log.logger("退出visitSubID方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        单个变量做常量，同上
     */
    @Override
    public TypeExpression visitSigID(CalcParser.SigIDContext ctx) {
        log.logger("进入visitSigID方法", 1);
        String sigId = ctx.ID().getText();
        SymbolNode idSymbol;
        if (paraMap.containsVariable(sigId)) {
            idSymbol = paraMap.getVariable(sigId);
            expressionStack.push(sigId);
            log.logger("退出visitSigID方法", 1);
            return idSymbol.getSymbolType();
        } else {
            // 添加到错误流中
            undefineID(ctx.ID().getSymbol());
            log.logger("退出visitSigID方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }

    }

    /*
        正的数字作为常数：ADD NUM
     */
    @Override
    public TypeExpression visitAddNum(CalcParser.AddNumContext ctx) {
        log.logger("进入visitAddNum方法", 1);
        // getText表示获取这个数字的字符串形式
        String num = ctx.NUM().getText();
        // 通过判断有没有小数点来判断是整数还是实数
        if (num.contains(".")) {
            if (periodRead) {
                periodStack.push(Double.parseDouble(num));
            }
            expressionStack.push(Double.parseDouble(num));
            log.logger("退出visitAddNum方法", 1);
            return new TypeExpression(BaseTypeEnum.REAL);
        } else {
            if (periodRead) {
                periodStack.push(Integer.parseInt(num));
            }
            expressionStack.push(Integer.parseInt(num));
            log.logger("退出visitAddNum方法", 1);
            return new TypeExpression(BaseTypeEnum.INTEGER);
        }
    }

    /*
        负的数字作为常数：SUB NUM
        同上
     */
    @Override
    public TypeExpression visitSubNum(CalcParser.SubNumContext ctx) {
        log.logger("进入visitSubNum方法", 1);
        String num = ctx.NUM().getText();

        if (num.contains(".")) {
            if (periodRead) {
                //负值
                periodStack.push(-Double.parseDouble(num));
            }
            expressionStack.push(-Double.parseDouble(num));
            log.logger("退出visitSubNum方法", 1);
            return new TypeExpression(BaseTypeEnum.REAL);
        } else {
            if (periodRead) {
                periodStack.push(-Integer.parseInt(num));
            }
            expressionStack.push(-Integer.parseInt(num));
            log.logger("退出visitSubNum方法", 1);
            return new TypeExpression(BaseTypeEnum.INTEGER);
        }
    }

    /*
        数字常量
        同上
     */
    @Override
    public TypeExpression visitSigNum(CalcParser.SigNumContext ctx) {
        log.logger("进入visitSigNum方法", 1);
        String num = ctx.NUM().getText();
        if (num.contains(".")) {
            if (periodRead) {
                periodStack.push(Double.parseDouble(num));
            }
            expressionStack.push(Double.parseDouble(num));
            log.logger("退出visitSigNum方法", 1);
            return new TypeExpression(BaseTypeEnum.REAL);
        } else {
            if (periodRead) {
                periodStack.push(Integer.parseInt(num));
            }
            expressionStack.push(Integer.parseInt(num));
            log.logger("退出visitSigNum方法", 1);
            return new TypeExpression(BaseTypeEnum.INTEGER);
        }
    }

    /*
        单个字符常量：SIG_QUT LETTER SIG_QUT
     */
    @Override
    public TypeExpression visitSigLetter(CalcParser.SigLetterContext ctx) {
        log.logger("进入visitSigLetter方法", 1);
        //'a'
        // 字符常量的字符串中包含单引号
        if (periodRead) {
            // 当产生数组时，因为需要计算数组的范围，所以只要压入字母值就可以
            periodStack.push(ctx.getText().charAt(1));
        }
        expressionStack.push(ctx.getText());
        log.logger("退出visitSigLetter方法", 1);
        return new TypeExpression(BaseTypeEnum.CHAR);
    }

    /*
        类型声明，被type和分号包裹
        整个程序也只有这个一个声明的地方
        语法：TYPE type_declaration SEMICOLON
     */
    @Override
    public TypeExpression visitTypeDecla(CalcParser.TypeDeclaContext ctx) {
        log.logger("进入visitTypeDecla方法", 1);
        TypeExpression typeDeclaExp = (TypeExpression) visit(ctx.type_declaration());
        log.logger("退出visitTypeDecla方法", 1);
        return typeDeclaExp;
    }

    /*
        单个类型的声明
        符号表构建
        语法：ID EQUAL type
     */
    @Override
    public TypeExpression visitSigType(CalcParser.SigTypeContext ctx) {
        //这地方才是真正创建出来一个type的地方
        log.logger("进入visitType方法", 1);
        TypeExpression sigTypeExp;
        String idName = ctx.ID().getText();
        // 每次都需要去检查定义的type是否在当前代码块中重名
        if (paraMap.topContainsSymbol(idName)) {
            // 变量重复定义
            redefineID(ctx.ID().getSymbol());
            sigTypeExp = new TypeExpression(ToolTypeEnum.ERROR);
        } else {
            // 在访问完type之后，会有这个type的类型和大小被压入栈中
            TypeExpression idType = (TypeExpression) visit(ctx.type());
            // 需要去改变size
            int typeSize = typeSizeStack.pop();
            // 创建新的type变量
            Object typeObj = expressionStack.pop();
            // 产生三地址代码
            midCode.addNewCode(new MidCodeNode(OperationEnum.NEW_TYPE, typeObj, idName));
            String typeSting = typeObj.toString();
            int idDepth;
            if (typeSting.equals("real") || typeSting.equals("boolean")
                    || typeSting.equals("integer") || typeSting.equals("char")) {
                idDepth = 0;
            } else {
                idDepth = idType.getArrayDepth();
            }
            TypeDeclaNode typeDeclaNode = new TypeDeclaNode(idName, idType, idDepth, typeSize);
            // 将这个type加入到符号表中
            paraMap.putType(idName, typeDeclaNode);
            // 压入void表示一切正常
            sigTypeExp = new TypeExpression(ToolTypeEnum.VOID);
        }
        log.logger("退出visitType方法", 1);
        return sigTypeExp;
    }

    /*
        多个类型的声明
        语法：type_declaration SEMICOLON ID EQUAL type
        用分号分隔
     */
    @Override
    public TypeExpression visitMultiType(CalcParser.MultiTypeContext ctx) {
        log.logger("进入visitMultiType方法", 1);
        TypeExpression innerType = (TypeExpression) visit(ctx.type_declaration());
        String idName = ctx.ID().getText();
        if (paraMap.topContainsSymbol(idName)) {
            // 变量重复定义
            redefineID(ctx.ID().getSymbol());
            return new TypeExpression(ToolTypeEnum.ERROR);
        } else {
            TypeExpression idType = (TypeExpression) visit(ctx.type());
            // 需要去设置typeSize
            int typeSize = typeSizeStack.pop();
            Object typeObj = expressionStack.pop();
            midCode.addNewCode(new MidCodeNode(OperationEnum.NEW_TYPE, typeObj, idName));
            int idDepth = idType.getArrayDepth();

            TypeDeclaNode typeDeclaNode = new TypeDeclaNode(idName, idType, idDepth, typeSize);
            paraMap.putType(idName, typeDeclaNode);
        }
        if (innerType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitMultiType方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitMultiType方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        基本类型声明体：standard_type
        返回类型表达式
     */
    @Override
    public TypeExpression visitBaseTypeExt(CalcParser.BaseTypeExtContext ctx) {
        log.logger("进入visitBaseTypeExt方法", 1);
        TypeExpression baseType = (TypeExpression) visit(ctx.standard_type());
        //standard_type已经压栈了
        String stdType = expressionStack.peek().toString();
        char firstChar = stdType.charAt(0);
        //把基本类型所占据的空间压入栈中
        //通过首字母来判断是什么类型，然后返回相应的大小
        if (firstChar == 'i') {
            typeSizeStack.push(4);
        } else if (firstChar == 'r') {
            typeSizeStack.push(4);
        } else if (firstChar == 'b') {
            typeSizeStack.push(1);
        } else if (firstChar == 'c') {
            typeSizeStack.push(1);
        }
        log.logger("退出visitBaseTypeExt方法", 1);
        return baseType;
    }

    /*
        记录的声明体
        语法：RECORD record_body? END
        返回类型表达式
     */
    @Override
    public TypeExpression visitRecordExt(CalcParser.RecordExtContext ctx) {
        log.logger("进入visitRecordExt方法", 1);
        TypeExpression recordType = null;
        if (ctx.record_body() != null) {
            // 这里声明俩Map来保存字段的类型和大小
            HashMap<String, String> topVarMap = new HashMap<>();
            HashMap<String, Integer> topSizeMap = new HashMap<>();
            // 因为可以递归生成，所以使用一个成员变量栈来保存
            recordVarListMap.push(topVarMap);
            recordVarSizeMap.push(topSizeMap);
            // 访问body
            recordType = (TypeExpression) visit(ctx.record_body());

            //这里已经获取到了该记录所有的字段-类型
            topVarMap = recordVarListMap.pop();
            topSizeMap = recordVarSizeMap.pop();

            String recordName = paraGenerate.nextPara();
            midCode.addNewCode(new MidCodeNode(OperationEnum.RECORD_START, recordName));

            // 这里为了节约内存空间，所以做了内存的对齐，实际上也只是简简单单的排序了而已
            // 要对记录的顺序做排序的，需要对齐
            LinkedList<VarElement> varElementList = memoryAlign(topVarMap, topSizeMap);

            //依次给每个字段加入到三地址代码中
            //递归的record已经在访问body的时候产生过了
            for (VarElement varEle : varElementList) {
                midCode.addNewCode(new MidCodeNode(OperationEnum.ADD_NEW_RECORD_ELEMENT, varEle.getVarSize(), varEle.getVarType(), varEle.getVarName()));
            }

            midCode.addNewCode(new MidCodeNode(OperationEnum.RECORD_END, recordName));
            // 压入record的名字
            expressionStack.push(recordName);
            // 这里用流来对大小求和
            Collection<Integer> eleSizeSet = topSizeMap.values();
            int recordTotalSize = eleSizeSet.parallelStream().mapToInt(Integer::intValue).sum();
            // 把整个record的大小也压入栈中
            typeSizeStack.push(recordTotalSize);
        }
        log.logger("退出visitRecordExt方法", 1);
        return recordType;
    }

    /*
        数组的声明体
        语法：ARRAY LEFT_BRACKET periods RIGHT_BRACKET OF type
        返回类型表达式
     */
    @Override
    public TypeExpression visitPeriodExt(CalcParser.PeriodExtContext ctx) {
        // 数组的声明
        log.logger("进入visitPeriodExt方法", 1);
        LinkedList<TypeExpression> periodType = (LinkedList<TypeExpression>) visit(ctx.periods());
        // 获取范围
        int size = periodType.size();
        // 将数组深度内的范围加入到链表中，防止类型错误
        LinkedList<ArrayRange> periodRange = new LinkedList<>();
        for (int i = 0; i < size; i++) {
            periodRange.add(periodRangeStack.pop());
        }

        TypeExpression contentType = (TypeExpression) visit(ctx.type());
        int elementSize = typeSizeStack.pop();
        Object typeObj = expressionStack.pop();
        //数组的元素个数
        int arrayNumber;

        ArrayList<TypeNode> son = new ArrayList<>(2);
        son.add(contentType.getTypeNode());

        //这里对范围求值，以此来计算数组包含的元素个数
        ArrayRange rootRange = periodRange.pollFirst();
        int indexStart;
        int indexEnd;
        if (rootRange.isInt()) {
            indexStart = (int) rootRange.getStart();
            indexEnd = (int) rootRange.getEnd();
        } else {
            indexStart = (char) rootRange.getStart() - 'a';
            indexEnd = (char) rootRange.getEnd() - 'a';
        }
        // 数组的数据结构大概是
        /*
                ARRAY
                |   \
                Type ArrayRange
                这两个孩子，如果是嵌套数组的话则Type为ARRAY
                大概是这个样子
                ARRAY
                |   \
                Type ArrayRange
                |  \
                |   \
                |    \
                real  ArrayRange
         */
        son.add(new ArrayRange(rootRange.isInt(), rootRange.getStart(), rootRange.getEnd()));

        arrayNumber = indexEnd - indexStart + 1;

        // 数组的产生从最深处开始，即先从右侧开始声明，然后才是左侧的
        // 根数组
        int depth = 1;
        TypeConstructor array = new TypeConstructor(TypeConstructorEnum.ARRAY, son);
        array.setArrayDepth(depth);

        Queue<String> arrayNameQueue = new LinkedList<>();
        Queue<Object> typeQueue = new LinkedList<>();
        Queue<Integer> arrayLengthQueue = new LinkedList<>();

        String nowContentType = paraGenerate.nextPara();
        arrayNameQueue.add(nowContentType);
        typeQueue.add(typeObj);
        arrayLengthQueue.add(arrayNumber);

        for (int i = periodType.size() - 2; i >= 0; i--) {
            depth++;
            ArrayList<TypeNode> outerSon = new ArrayList<>(2);
            outerSon.add(array);
            rootRange = periodRange.pollFirst();
            indexStart = (int) rootRange.getStart();
            indexEnd = (int) rootRange.getEnd();
            arrayNumber *= (indexEnd - indexStart + 1);
            outerSon.add(new ArrayRange(rootRange.isInt(), indexStart, indexEnd));
            TypeConstructor newArray = new TypeConstructor(TypeConstructorEnum.ARRAY, outerSon);
            newArray.setArrayDepth(depth);
            array = newArray;

            typeQueue.add(nowContentType);
            nowContentType = paraGenerate.nextPara();
            arrayNameQueue.add(nowContentType);
            arrayLengthQueue.add(indexEnd - indexStart + 1);
        }
        // 然后获得一个新的变量，产生数组的三地址代码
        while (!arrayNameQueue.isEmpty()) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.NEW_ARRAY, typeQueue.poll(), arrayLengthQueue.poll(), arrayNameQueue.poll()));
        }
//        String arrayName = paraGenerate.nextPara();
//        midCode.addNewCode(new MidCodeNode(OperationEnum.NEW_ARRAY, typeObj, depth, arrayName));
        expressionStack.push(nowContentType);
//        if (recordRead)
//            recordSizeStack.push(elementSize * arrayNumber);
//        else
        // 将数组的大小压入栈中
        typeSizeStack.push(elementSize * arrayNumber);
        log.logger("退出visitPeriodExt方法", 1);
        return new TypeExpression(array);
    }

    /*
        ID也可以当做变量声明的类型（仅当ID已经被定义为type时）
     */
    @Override
    public TypeExpression visitDefinedRecord(CalcParser.DefinedRecordContext ctx) {
        String typeName = ctx.ID().getText();
        // 对ID做类型检查，检查是否为定义过的type
        if (paraMap.containsType(typeName)) {
            expressionStack.push(typeName);
            int typeSize = paraMap.getType(typeName).getSize();
//            if (recordRead)
//                recordSizeStack.push(typeSize);
//            else
            typeSizeStack.push(typeSize);
            return paraMap.getType(typeName).getTypeExpression();
        } else {
            // 未定义，错误流
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine();
            String tips = "类型：'" + typeName + "'未定义，请检查声明语句是否正确";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
        }
        return new TypeExpression(ToolTypeEnum.ERROR);
    }

    /*
        基本类型
        INTEGER|REAL|BOOLEAN|CHAR
     */
    @Override
    public TypeExpression visitStandard_type(CalcParser.Standard_typeContext ctx) {
        log.logger("进入visitStandard_type方法", 1);
        //将基本类型符号压入到栈中
        expressionStack.push(ctx.getText());
        log.logger("退出visitStandard_type方法", 1);
        return standTypeDetect(ctx.getText());
    }

    /*
        记录的定义体
     */
    @Override
    public TypeExpression visitRecordBody(CalcParser.RecordBodyContext ctx) {
        log.logger("进入visitRecordBody方法", 1);
//        recordRead = true;

        LinkedList<TypeExpression> innerType = (LinkedList<TypeExpression>) visit(ctx.var_declaration());


        ArrayList<TypeNode> sonList = new ArrayList<>(innerType.size());
        //将链表中的每一项都加入到sonList中，以便于构造记录类型
        for (TypeExpression type : innerType) {
            sonList.add(type.getTypeNode());
        }

        TypeConstructor typeConstructor = new TypeConstructor(TypeConstructorEnum.RECOR, sonList);
        TypeExpression resultType = new TypeExpression(typeConstructor);

//        recordRead = false;
        log.logger("退出visitRecordBody方法", 1);
        return resultType;
    }

    /*
        多个范围，用逗号分隔
     */
    @Override
    public LinkedList<TypeExpression> visitGetPeriodList(CalcParser.GetPeriodListContext ctx) {
        // 多个范围的声明
        log.logger("进入visitGetPeriodList方法", 1);
        LinkedList<TypeExpression> multiType = new LinkedList<>();
        multiType.addAll((LinkedList<TypeExpression>) visit(ctx.periods()));

        multiType.add((TypeExpression) visit(ctx.period()));
//        ArrayRange arrayRange = periodRangeStack.pop();
//        String newRange = paraGenerate.nextPara();
//        midCode.addNewCode(new MidCodeNode(OperationEnum.ARRAY_RANGE, arrayRange.getStart(), arrayRange.getEnd(), newRange));
        log.logger("退出visitGetPeriodList方法", 1);
        return multiType;
    }

    /*
        单个范围（嵌套终止）
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigPeriod(CalcParser.GetSigPeriodContext ctx) {
        // 单个范围的声明
        log.logger("进入visitGetSigPeriod方法", 1);
        LinkedList<TypeExpression> sigType = new LinkedList<>();
        sigType.add((TypeExpression) visit(ctx.period()));

        log.logger("退出visitGetSigPeriod方法", 1);
        return sigType;
    }

    /*
        范围语句，就是带..的
        检测一下左边是不是比右边小
        语法：const_variable DOUBLE_DOT const_variable
     */
    @Override
    public TypeExpression visitGetPeriod(CalcParser.GetPeriodContext ctx) {
        log.logger("进入visitGetPeriod方法", 1);
        TypeExpression periodType;
        periodRead = true;
        TypeExpression leftValue = (TypeExpression) visit(ctx.const_variable(0));
        Object leftValueObj = expressionStack.pop();
        TypeExpression rightValue = (TypeExpression) visit(ctx.const_variable(1));
        Object rightValueObj = expressionStack.pop();

        periodRead = false;
        if (leftValue.typeEquals(rightValue)) {
            if (periodStack.size() == 2) {
                Object right = periodStack.pop();
                Object left = periodStack.pop();
                if (right instanceof Double) {
                    // 实数不能当做数组起始
                    int line = ctx.DOUBLE_DOT().getSymbol().getLine();
                    int inLine = ctx.DOUBLE_DOT().getSymbol().getCharPositionInLine() + 1;
                    String tips = "无法创建实数为边界的数组";
                    errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
                    periodType = new TypeExpression(ToolTypeEnum.ERROR);
                } else if (right instanceof Integer) {
                    if ((Integer) left > (Integer) right) {
                        // 数组声明错误
                        int line = ctx.DOUBLE_DOT().getSymbol().getLine();
                        int inLine = ctx.DOUBLE_DOT().getSymbol().getCharPositionInLine() + 1;
                        String tips = "数组边界范围不符合要求，请检查左部数据是否小于右部";
                        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.PERIOD_ERROR, tips));
                        periodType = new TypeExpression(ToolTypeEnum.ERROR);
                    } else {
                        periodRangeStack.push(new ArrayRange(true, leftValueObj, rightValueObj));
                        periodType = new TypeExpression(BaseTypeEnum.INTEGER);
                    }
                } else if (right instanceof Character) {
                    if ((Character) left > (Character) right) {
                        periodType = new TypeExpression(ToolTypeEnum.ERROR);
                    } else {
                        periodRangeStack.push(new ArrayRange(false, leftValueObj.toString().charAt(1), rightValueObj.toString().charAt(1)));
                        periodType = new TypeExpression(BaseTypeEnum.CHAR);
                    }
                } else {
                    periodType = new TypeExpression(ToolTypeEnum.ERROR);
                }
            } else {
                periodType = leftValue;
            }
        } else {
            // 类型不匹配，错误流
            int line = ctx.DOUBLE_DOT().getSymbol().getLine();
            int inLine = ctx.DOUBLE_DOT().getSymbol().getCharPositionInLine();
            String tips = "两侧边界类型不一致，请检查变量声明";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.PERIOD_ERROR, tips));
            periodType = new TypeExpression(ToolTypeEnum.ERROR);
        }
        periodStack.clear();
        log.logger("退出visitGetPeriod方法", 1);
        return periodType;
    }

    /*
        变量声明语句
        全局的，也是一个程序只有这一个变量声明的地方
        将这里面的变量全都加入到符号表中
     */
    @Override
    public TypeExpression visitVarDecla(CalcParser.VarDeclaContext ctx) {
        log.logger("进入visitVarDecla方法", 1);
        HashMap<String, String> varMap = new HashMap<>();
        HashMap<String, Integer> varSizeMap = new HashMap<>();
        //由于集中式的声明变量，因此为了节约内存空间我们也按照内存对其的顺序来声明
        recordVarListMap.push(varMap);
        recordVarSizeMap.push(varSizeMap);
        LinkedList<TypeExpression> varDeclarations = (LinkedList<TypeExpression>) visit(ctx.var_declaration());

        for (TypeExpression typeExpression : varDeclarations) {
            TypeConstructor typeNode = (TypeConstructor) typeExpression.getTypeNode();
            TypeNode nameNode = typeNode.getSonList().get(0);
            String paraName;

            paraName = ((ParaName) nameNode).getParaName();

            TypeNode paraType = typeNode.getSonList().get(1);
            TypeExpression paraExp = new TypeExpression(paraType);
            if (paraType instanceof BaseTypeEnum) {
                paraMap.putVariable(paraName, new SymbolNode(paraName, paraExp, false, 0));
            } else if (paraType instanceof TypeConstructor) {
                paraMap.putVariable(paraName, new SymbolNode(paraName, paraExp, false, paraExp.getArrayDepth()));
            } else {
                log.logger("退出visitVarDecla方法", 1);
                return new TypeExpression(ToolTypeEnum.ERROR);
            }
        }

        varMap = recordVarListMap.pop();
        varSizeMap = recordVarSizeMap.pop();
        // 变量的声明，进行内存对齐
        LinkedList<VarElement> varElementList = memoryAlign(varMap, varSizeMap);
        for (VarElement varEle : varElementList) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.DECLA, varEle.getVarSize(), varEle.getVarType(), varEle.getVarName()));
        }

        log.logger("退出visitVarDecla方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        多个类型的变量声明
        语法：var_declaration SEMICOLON identifier_list COLON type
     */
    @Override
    public LinkedList<TypeExpression> visitGetVarDeclaList(CalcParser.GetVarDeclaListContext ctx) {
        log.logger("进入visitGetVarDeclaList方法", 1);
        //递归获取内部的类型
        LinkedList<TypeExpression> innerTypeExp = (LinkedList<TypeExpression>) visit(ctx.var_declaration());
        //类似单个类型声明的获取
        LinkedList<String> idNameList = (LinkedList<String>) visit(ctx.identifier_list());
//        recordRead=false;
        TypeExpression typeExpCon = (TypeExpression) visit(ctx.type());
//        recordRead=true;
        int typeSize = typeSizeStack.pop();
        Object typeObj = expressionStack.pop();

        TypeNode type = typeExpCon.getTypeNode();
        //不应该加入到paraMap中
        HashMap<String, String> varTypeMap = recordVarListMap.peek();
        HashMap<String, Integer> varSizeMap = recordVarSizeMap.peek();
        for (String idName : idNameList) {
            if (varTypeMap.containsKey(idName)) {
                int line = ctx.COLON().getSymbol().getLine();
                int inLine = ctx.COLON().getSymbol().getCharPositionInLine() - 1;
                String tips = "变量:'" + idName + "'重复定义";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
            } else {
                //把元素的类型和大小都压到map里
                varTypeMap.put(idName, typeObj.toString());
                varSizeMap.put(idName, typeSize);
            }
        }

        LinkedList<TypeExpression> outerTypeList = new LinkedList<>();
        for (String element : idNameList) {
            ArrayList<TypeNode> son = new ArrayList<>(2);
            //把字符串链表转换成单个Node变量
            son.add(new ParaName(element));
            son.add(type);
            //构造出一个类型构造器
            TypeConstructor typeConstructor = new TypeConstructor(TypeConstructorEnum.DESCAR, son);
            outerTypeList.add(new TypeExpression(typeConstructor));
        }
        //把内部的和外部的结合起来
        innerTypeExp.addAll(outerTypeList);
        log.logger("退出visitGetVarDeclaList方法", 1);
        return innerTypeExp;
    }

    /*
        单个类型的变量声明（嵌套终止）
        语法：identifier_list COLON type
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigVarDecla(CalcParser.GetSigVarDeclaContext ctx) {
        log.logger("进入visitGetSigVarDecla方法", 1);
        //虽然是链表但是实际上只有一个数据
        LinkedList<TypeExpression> sigVarDeclaration = new LinkedList<>();

        //获取字段名的列表
        LinkedList<String> idNameList = (LinkedList<String>) visit(ctx.identifier_list());


        TypeExpression typeExpCon = (TypeExpression) visit(ctx.type());
        TypeNode typeNode = typeExpCon.getTypeNode();
        for (String element : idNameList) {
            ArrayList<TypeNode> son = new ArrayList<>(2);
            //把字符串链表转换成单个Node变量
            son.add(new ParaName(element));
            son.add(typeNode);
            //构造出一个类型构造器
            TypeConstructor typeConstructor = new TypeConstructor(TypeConstructorEnum.DESCAR, son);
            sigVarDeclaration.add(new TypeExpression(typeConstructor));
        }

        int typeSize = typeSizeStack.pop();
        Object typeObj = expressionStack.pop();
        TypeNode type = typeExpCon.getTypeNode();
        // 不应该加入到paraMap中
        HashMap<String, String> varTypeMap = recordVarListMap.peek();
        HashMap<String, Integer> varSizeMap = recordVarSizeMap.peek();
        for (String idName : idNameList) {
            if (varTypeMap.containsKey(idName)) {
                int line = ctx.COLON().getSymbol().getLine();
                int inLine = ctx.COLON().getSymbol().getCharPositionInLine() - 1;
                String tips = "变量:'" + idName + "'重复定义";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
            } else {
                //把元素的类型和大小都压到map里
                varTypeMap.put(idName, typeObj.toString());
                varSizeMap.put(idName, typeSize);
            }
        }

        log.logger("退出visitGetSigVarDecla方法", 1);
        return sigVarDeclaration;
    }

    /*
        单个子程序的定义
        语法：subprogram_declaration SEMICOLON
        分号结尾
     */
    @Override
    public TypeExpression visitGetSigSubProDecla(CalcParser.GetSigSubProDeclaContext ctx) {
        log.logger("进入visitGetSigSubProDecla方法", 1);
        // 单个子程序的定义
        TypeExpression sigSubProType = (TypeExpression) visit(ctx.subprogram_declaration());
        log.logger("退出visitGetSigSubProDecla方法", 1);
        return sigSubProType;
    }

    /*
        多个子程序的定义，分号分隔
        语法：subprogram_declarations subprogram_declaration SEMICOLON
     */
    @Override
    public TypeExpression visitGetSubProDeclaList(CalcParser.GetSubProDeclaListContext ctx) {
        log.logger("进入visitGetSubProDeclaList方法", 1);
        // 多个子程序的定义
        TypeExpression innerType = (TypeExpression) visit(ctx.subprogram_declarations());
        TypeExpression outerType = (TypeExpression) visit(ctx.subprogram_declaration());
        //递归检查子程序的定义中是否存在
        if (innerType.typeEquals(ToolTypeEnum.ERROR) || outerType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitGetSubProDeclaList方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitGetSubProDeclaList方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        单个子程序的定义，有程序体的
        语法：subprogram_head program_body
     */
    @Override
    public TypeExpression visitSubProgramDecla(CalcParser.SubProgramDeclaContext ctx) {
        log.logger("进入visitSubProgramDecla方法", 1);
        // 分开遍历即可，注意segment的新建
        TypeExpression headType = (TypeExpression) visit(ctx.subprogram_head());
        paraMap.location();
        // 如果是函数的话需要新创建一个变量，作为返回值
        String funcName = funcNameStack.pop();
        //用@来标记是函数（有返回值的）
        //@函数名
        boolean isFunc = false;
        if (funcName.contains("@")) {
            isFunc = true;
            funcName = funcName.substring(1);
            TypeExpression returnType = returnTypeStack.pop();
            SymbolNode returnSymbol = new SymbolNode(funcName, returnType, false, 0);
            paraMap.putVariable(funcName, returnSymbol);

        }
        TypeExpression bodyType = (TypeExpression) visit(ctx.program_body());
        if (isFunc) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.RETURN, funcName));
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROGRAM_BODY_END));
        //重定位
        paraMap.relocation();
        if (headType.typeEquals(ToolTypeEnum.ERROR) || bodyType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitSubProgramDecla方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitSubProgramDecla方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        子程序的声明部分
        语法：FUNCTION ID formal_parameter? COLON standard_type SEMICOLON
        有返回值的，冒号后面就是返回值
     */
    @Override
    public TypeExpression visitFuncSubProgram(CalcParser.FuncSubProgramContext ctx) {
        log.logger("进入visitFuncSubProgram方法", 1);
        // 子函数
        String funcName = ctx.ID().getText();
        funcNameStack.push("@" + funcName);
        BaseTypeEnum returnType = (BaseTypeEnum) ((TypeExpression) visit(ctx.standard_type())).getTypeNode();
        if (paraMap.containsSymbol(funcName)) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.FUNC_START, funcName));
            returnTypeStack.push(new TypeExpression(returnType));
            //判断是否有参数
            if (ctx.formal_parameter() != null) {
                LinkedList<TypeExpression> paraList = (LinkedList<TypeExpression>) visit(ctx.formal_parameter());
                int paraSize = paraList.size();
                Stack<ParaTrans> paraSack = new Stack<>();
                for (int i = 0; i < paraSize; i++) {
                    paraSack.push(paraTransStack.pop());
                }

                TypeExpression[] paraArray = paraList.toArray(new TypeExpression[paraSize]);
                HashSet<Integer> referIndex = new HashSet<>();
                for (int i = 0; i < paraSize; i++) {
                    if (((TypeConstructor) paraArray[i].getTypeNode()).getType() == TypeConstructorEnum.FUNC) {
                        referIndex.add(i);
                        //复原
                        ((TypeConstructor) paraArray[i].getTypeNode()).setType(TypeConstructorEnum.DESCAR);
                    }
                }
                while (!paraSack.isEmpty()) {
                    ParaTrans nowPara = paraSack.pop();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.PARAM, nowPara.isRefer(), nowPara.getType(), nowPara.getParaName()));
                }
                FunctionNode newFunc = new FunctionNode(funcName, returnType, paraArray.length, paraArray, referIndex);
                paraMap.putFunction(funcName, newFunc);
            }
        } else {
            redefineID(ctx.ID().getSymbol());
            // 错误流
            midCode.addNewCode(new MidCodeNode(OperationEnum.FUNC_END, funcName));
            midCode.addNewCode(new MidCodeNode(OperationEnum.DECLA, returnType, funcName));
            log.logger("退出visitFuncSubProgram方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.FUNC_END, funcName));
        midCode.addNewCode(new MidCodeNode(OperationEnum.DECLA, returnType, funcName));
        log.logger("退出visitFuncSubProgram方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        声明过程的子程序
        语法：PROCEDURE ID formal_parameter? SEMICOLON
        无返回值
     */
    @Override
    public TypeExpression visitProSubProgram(CalcParser.ProSubProgramContext ctx) {
        log.logger("进入visitProSubProgram方法", 1);
        // 子过程
        String proName = ctx.ID().getText();
        funcNameStack.push(proName);
        if (paraMap.containsSymbol(proName)) {
            //判断是否存在参数
            if (ctx.formal_parameter() != null) {
                midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_START, proName));
                LinkedList<TypeExpression> paraList = (LinkedList<TypeExpression>) visit(ctx.formal_parameter());
                int paraSize = paraList.size();
                Stack<ParaTrans> paraSack = new Stack<>();
                for (int i = 0; i < paraSize; i++) {
                    paraSack.push(paraTransStack.pop());
                }

                TypeExpression[] paraArray = paraList.toArray(new TypeExpression[paraSize]);
                HashSet<Integer> referIndex = new HashSet<>();
                for (int i = 0; i < paraArray.length; i++) {
                    if (((TypeConstructor) paraArray[i].getTypeNode()).getType() == TypeConstructorEnum.FUNC) {
                        referIndex.add(i);
                        ((TypeConstructor) paraArray[i].getTypeNode()).setType(TypeConstructorEnum.DESCAR);
                    }
                }
                //创建过程参数
                while (!paraSack.isEmpty()) {
                    ParaTrans nowPara = paraSack.pop();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.PARAM, nowPara.isRefer(), nowPara.getType(), nowPara.getParaName()));
                }
                FunctionNode newFunc = new FunctionNode(proName, null, paraArray.length, paraArray, referIndex);
                paraMap.putFunction(proName, newFunc);
            } else {
                //无参数
                FunctionNode newFunc = new FunctionNode(proName, null, 0, null, null);
                paraMap.putFunction(proName, newFunc);
                midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_END, proName));
                log.logger("退出visitProSubProgram方法", 1);
                return new TypeExpression(ToolTypeEnum.VOID);
            }
        } else {
            redefineID(ctx.ID().getSymbol());
            // 错误流，重名过程
            midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_END, proName));
            log.logger("退出visitProSubProgram方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.PROC_END, proName));
        log.logger("退出visitProSubProgram方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        参数表
        注意参数表本身可以为空，但是因为ANTLR语法的问题，我把空的问题留给了上一级的？去判断
        语法：LEFT_BRA parameter_lists RIGHT_BRA
        参数表内部是多个变量的声明，变量名和类型
     */
    @Override
    public LinkedList<TypeExpression> visitFormalPara(CalcParser.FormalParaContext ctx) {
        log.logger("进入visitFormalPara方法", 1);
        // 参数表部分
        LinkedList<TypeExpression> paraTypeList = (LinkedList<TypeExpression>) visit(ctx.parameter_lists());
        log.logger("退出visitFormalPara方法", 1);
        return paraTypeList;
    }

    /*
        单个参数声明（递归终止）
        可以是带var的也可以不是
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigParaList(CalcParser.GetSigParaListContext ctx) {
        log.logger("进入visitGetSigParaList方法", 1);
        //  单个参数表
        LinkedList<TypeExpression> sigParaList = (LinkedList<TypeExpression>) visit(ctx.parameter_list());
        log.logger("退出visitGetSigParaList方法", 1);
        return sigParaList;
    }

    /*
        多条参数声明
        语法：parameter_lists SEMICOLON parameter_list
        每个参数之间用分号分隔
     */
    @Override
    public LinkedList<TypeExpression> visitGetParaLists(CalcParser.GetParaListsContext ctx) {
        log.logger("进入visitGetParaLists方法", 1);
        LinkedList<TypeExpression> innerList = (LinkedList<TypeExpression>) visit(ctx.parameter_lists());
        innerList.addAll((LinkedList<TypeExpression>) visit(ctx.parameter_list()));
        log.logger("退出visitGetParaLists方法", 1);
        return innerList;
    }

    /*
        参数声明带var的
     */
    @Override
    public LinkedList<TypeExpression> visitParaVar(CalcParser.ParaVarContext ctx) {
        log.logger("进入visitParaVar方法", 1);
        LinkedList<TypeExpression> paraVarList = (LinkedList<TypeExpression>) visit(ctx.var_parameter());
        log.logger("退出visitParaVar方法", 1);
        return paraVarList;
    }

    /*
        不带var的参数声明
     */
    @Override
    public LinkedList<TypeExpression> visitParaValue(CalcParser.ParaValueContext ctx) {
        log.logger("进入visitParaValue方法", 1);
        LinkedList<TypeExpression> paraValueList = (LinkedList<TypeExpression>) visit(ctx.value_parameter());
        log.logger("退出visitParaValue方法", 1);
        return paraValueList;
    }

    /*
        带var的参数声明
        实际上只是加了一个var在前面而已
        带var的表示是使用引用传递
        语法：VAR value_parameter
     */
    @Override
    public LinkedList<TypeExpression> visitVarPara(CalcParser.VarParaContext ctx) {
        log.logger("进入visitVarPara方法", 1);
        // 带var的，也是递归
        LinkedList<TypeExpression> varList = (LinkedList<TypeExpression>) visit(ctx.value_parameter());
        int paraSize = varList.size();
        Stack<ParaTrans> referParaTrans = new Stack<>();
        for (int i = 0; i < paraSize; i++) {
            referParaTrans.push(paraTransStack.pop());
        }
        for (TypeExpression varType : varList) {
            TypeConstructor varCons = (TypeConstructor) varType.getTypeNode();
            //这里设定成FUNC表示引用传递，之后会恢复成DESCAR
            varCons.setType(TypeConstructorEnum.FUNC);
            //这里将引用传递压入栈中
            paraTransStack.push(referParaTrans.pop().setRefer(true));
        }
        log.logger("退出visitVarPara方法", 1);
        return varList;
    }

    /*
        参数声明
        语法：identifier_list COLON standard_type
        左部是变量名列表，右部是基本数据类型
     */
    @Override
    public LinkedList<TypeExpression> visitValueParaAssign(CalcParser.ValueParaAssignContext ctx) {
        log.logger("进入visitValueParaAssign方法", 1);
        // 变量赋类型
        LinkedList<String> idNameList = (LinkedList<String>) visit(ctx.identifier_list());
        TypeExpression idType = (TypeExpression) visit(ctx.standard_type());
        LinkedList<TypeExpression> paraList = new LinkedList<>();
        for (String idName : idNameList) {
            ArrayList<TypeNode> descarSon = new ArrayList<>(2);
            descarSon.add(new ParaName(idName));
            descarSon.add(idType.getTypeNode());
            //把参数压入栈中
            paraTransStack.push(new ParaTrans(false, idName, (idType.getTypeNode()).toString()));
            paraList.add(new TypeExpression(new TypeConstructor(TypeConstructorEnum.DESCAR, descarSon)));

            paraMap.putVariable(idName, new SymbolNode(idName, idType, false, 0));
        }
        log.logger("退出visitValueParaAssign方法", 1);
        return paraList;
    }

    /*
        被begin-end包裹的多条语句
        也可以为空（下面一条）
        语法：BEGIN statement_list END
     */
    @Override
    public TypeExpression visitGetComStatementList(CalcParser.GetComStatementListContext ctx) {
        log.logger("进入visitGetComStatementList方法", 1);
        // 带begin的多条语句
        TypeExpression statementType = (TypeExpression) visit(ctx.statement_list());
        log.logger("退出visitGetComStatementList方法", 1);
        return statementType;
    }

    /*
        空语句，就是说没有语句
        begin 后面就是 end
     */
    @Override
    public TypeExpression visitNullStatement(CalcParser.NullStatementContext ctx) {
        log.logger("进入visitNullStatement方法", 1);
        // 空语句
        log.logger("退出visitNullStatement方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        单个语句（递归终止）
     */
    @Override
    public TypeExpression visitGetSigStatement(CalcParser.GetSigStatementContext ctx) {
        log.logger("进入visitGetSigStatement方法", 1);
        // 单个语句
        TypeExpression sigStaType = (TypeExpression) visit(ctx.statement());
        log.logger("退出visitGetSigStatement方法", 1);
        return sigStaType;
    }

    /*
        多个语句组成的复合语句
        语法：statement_list SEMICOLON statement
        分号分隔
     */
    @Override
    public TypeExpression visitGetStatementList(CalcParser.GetStatementListContext ctx) {
        log.logger("进入visitGetStatementList方法", 1);
        // 嵌套语句
        TypeExpression multiType = (TypeExpression) visit(ctx.statement_list());
        TypeExpression sigType = (TypeExpression) visit(ctx.statement());
        if (multiType.typeEquals(ToolTypeEnum.ERROR) || sigType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitGetStatementList方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitGetStatementList方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        赋值语句
        语法：variable ASSIGNOP expression
        左部变量名，右部表达式
     */
    @Override
    public TypeExpression visitAssignStatement(CalcParser.AssignStatementContext ctx) {
        log.logger("进入visitAssignStatement方法", 1);
        // 赋值语句
        isLeftValue = true;
        TypeExpression varType = (TypeExpression) visit(ctx.variable());

        Object varObj = expressionStack.pop();
        isLeftValue = false;
        TypeExpression expType = (TypeExpression) visit(ctx.expression());
        Object expObj = expressionStack.pop();
        if (varType.typeEquals(expType) && !varType.typeEquals(ToolTypeEnum.ERROR)) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.ASSIGN, expObj, varObj));
            log.logger("退出visitAssignStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.VOID);
        } else {
            // 错误流，赋值语句类型不匹配
            int line = ctx.ASSIGNOP().getSymbol().getLine();
            int inLine = ctx.ASSIGNOP().getSymbol().getCharPositionInLine();
            String tips = "变量：'" + ctx.variable().getText() + "'与右值不匹配";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
            log.logger("退出visitAssignStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        过程调用语句
        注意检查调用格式
     */
    @Override
    public TypeExpression visitProCallStatement(CalcParser.ProCallStatementContext ctx) {
        log.logger("进入visitProCallStatement方法", 1);
        // 过程调用语句
        TypeExpression callType = (TypeExpression) visit(ctx.call_procedure_statement());
        log.logger("退出visitProCallStatement方法", 1);
        return callType;
    }

    /*
        复杂语句（多个语句）
     */
    @Override
    public TypeExpression visitComStatement(CalcParser.ComStatementContext ctx) {
        log.logger("进入visitComStatement方法", 1);
        // 复合语句
        TypeExpression comType = (TypeExpression) visit(ctx.compound_statement());
        log.logger("退出visitComStatement方法", 1);
        return comType;
    }

    /*
        write语句
     */
    @Override
    public TypeExpression visitWriteStatement(CalcParser.WriteStatementContext ctx) {
        log.logger("进入visitWriteStatement方法", 1);
        // write语句
        TypeExpression writeType = (TypeExpression) visit(ctx.write());
        log.logger("退出visitWriteStatement方法", 1);
        return writeType;

    }

    /*
        read语句
     */
    @Override
    public TypeExpression visitReadStatement(CalcParser.ReadStatementContext ctx) {
        log.logger("进入visitReadStatement方法", 1);
        // read语句
        TypeExpression readType = (TypeExpression) visit(ctx.read());
        log.logger("退出visitReadStatement方法", 1);
        return readType;
    }

    /*
        if-else语句
        检查语句中的表达式是不是布尔值
        语法：IF expression THEN statement else_part?
        注意也可以没有elsePart语句
     */
    @Override
    public TypeExpression visitIfStatement(CalcParser.IfStatementContext ctx) {
        log.logger("进入visitIfStatement方法", 1);
        TypeExpression exp = (TypeExpression) visit(ctx.expression());
        Object expObj = expressionStack.pop();
        if (!exp.typeEquals(BaseTypeEnum.BOOLEAN)) {
            // 错误流
            int line = ctx.IF().getSymbol().getLine();
            int inLine = ctx.IF().getSymbol().getCharPositionInLine() + 1;
            String tips = "if语句的条件不为布尔值，请检查表达式";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
            log.logger("退出visitIfStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        String ifLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, expObj, ifLabel));
        //先产生else的代码
        TypeExpression els = new TypeExpression(ToolTypeEnum.VOID);
        if (ctx.else_part() != null) {
            els = (TypeExpression) visit(ctx.else_part());
        }
        String elseLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, elseLabel));
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, ifLabel));
        TypeExpression sta = (TypeExpression) visit(ctx.statement());
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, elseLabel));
        if (els.typeEquals(ToolTypeEnum.ERROR) || sta.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitIfStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitIfStatement方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        case条件语句
        语法：CASE expression OF case_body? END
        注意也可以没有caseBody部分
        需要检查表达式的类型和caseBody中的类型是否一致
        而且caseBody中的类型也需要一致
     */
    @Override
    public TypeExpression visitCaseStatement(CalcParser.CaseStatementContext ctx) {
        log.logger("进入visitCaseStatement方法", 1);
        TypeExpression exp = (TypeExpression) visit(ctx.expression());

        Object expObj = expressionStack.pop();
        String tempValue = paraGenerate.nextPara();
        caseExpStack.push(tempValue);
        midCode.addNewCode(new MidCodeNode(OperationEnum.ASSIGN, expObj, tempValue));

        String startLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, startLabel));

        TypeExpression caseBody = (TypeExpression) visit(ctx.case_body());
        caseExpStack.pop();

        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, startLabel));
        if (exp.typeEquals(caseBody) && !caseBody.typeEquals(ToolTypeEnum.ERROR)) {
            for (MidCodeNode midCodeNode : caseNodeList) {

                if (midCodeNode.getOp() == OperationEnum.LABEL) {
                    midCode.addNewCode(midCodeNode);
                    continue;
                }
                //新增一个临时布尔变量跳转使用。22-5-4
                Object arg1 = midCodeNode.getArg1();
                Object arg2 = midCodeNode.getArg2();
                Object result = midCodeNode.getResult();
                String tempBool = paraGenerate.nextPara();
                midCode.addNewCode(new MidCodeNode(OperationEnum.EQUAL, arg1, arg2, tempBool));
                midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, tempBool, result));
            }
            log.logger("退出visitCaseStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.VOID);
        } else {
            //清空所有branch分支语句
            caseNodeList.clear();
            // 错误流，类型不匹配
            int line = ctx.CASE().getSymbol().getLine();
            int inLine = ctx.CASE().getSymbol().getCharPositionInLine() + 1;
            String tips = "case内的表达式和判断主体的表达式不匹配，请检查判断语句";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
            log.logger("退出visitCaseStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        while循环语句
        布尔值
        语法：WHILE expression DO statement
     */
    @Override
    public TypeExpression visitWhileStatement(CalcParser.WhileStatementContext ctx) {
        log.logger("进入visitWhileStatement方法", 1);

        //循环开始的地方
        String beginLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, beginLabel));
        TypeExpression expType = (TypeExpression) visit(ctx.expression());
        TypeExpression whileType = null;
        if (!expType.typeEquals(BaseTypeEnum.BOOLEAN)) {
            // 错误流，表达式返回值不为Boolean
            int line = ctx.WHILE().getSymbol().getLine();
            int inLine = ctx.WHILE().getSymbol().getCharPositionInLine() + 1;
            String tips = "while语句的条件不为布尔值，请检查表达式";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
            whileType = new TypeExpression(ToolTypeEnum.ERROR);
        } else {
            //做非运算
            Object ifObj = expressionStack.pop();
            String elseObj = paraGenerate.nextPara();
            midCode.addNewCode(new MidCodeNode(OperationEnum.NOT, elseObj, ifObj));
            //循环结束的地方
            String endLabel = paraGenerate.nextLabel();
            midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, elseObj, endLabel));
            TypeExpression staType = (TypeExpression) visit(ctx.statement());
            midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, beginLabel));
            //插入终止Label
            midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, endLabel));
            if (staType.typeEquals(ToolTypeEnum.ERROR)) {
                whileType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        }

        if (whileType == null) {
            log.logger("退出visitWhileStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.VOID);
        }
        log.logger("退出visitWhileStatement方法", 1);
        return whileType;
    }

    /*
        repeat循环语句
        语法：REPEAT statement_list UNTIL expression
     */
    @Override
    public TypeExpression visitRepeatStatement(CalcParser.RepeatStatementContext ctx) {
        log.logger("进入visitRepeatStatement方法", 1);
        //循环开始的地方
        TypeExpression resultType;
        String beginLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, beginLabel));
        TypeExpression staType = (TypeExpression) visit(ctx.statement_list());

        TypeExpression expType = (TypeExpression) visit(ctx.expression());
        Object expObj = expressionStack.pop();
        if (!expType.typeEquals(BaseTypeEnum.BOOLEAN)) {
            // 错误流
            int line = ctx.UNTIL().getSymbol().getLine();
            int inLine = ctx.UNTIL().getSymbol().getCharPositionInLine() + 1;
            String tips = "until表达式的结果不为布尔值";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
            log.logger("退出visitRepeatStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        } else {
            String notExp = paraGenerate.nextPara();
            midCode.addNewCode(new MidCodeNode(OperationEnum.NOT, expObj, notExp));
            midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, notExp, beginLabel));
        }
        if (staType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitRepeatStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitRepeatStatement方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        for循环语句
        布尔值
        语法：FOR ID ASSIGNOP expression updown expression DO statement
        感觉还需要检查一个to和downTo的方向问题
     */
    @Override
    public TypeExpression visitForStatement(CalcParser.ForStatementContext ctx) {
        log.logger("进入visitForStatement方法", 1);

        String forId = ctx.ID().getText();
        TypeExpression resultType = null;
        paraMap.location();
        boolean isUp = ctx.updown().getText().equals("to");
        TypeExpression left = (TypeExpression) visit(ctx.expression(0));
        //获取起始值
        Object startObj = expressionStack.pop();
//        String index = paraGenerate.nextPara();
        //产生初始化的代码
        midCode.addNewCode(new MidCodeNode(OperationEnum.ASSIGN, startObj, forId));
        //获取到定位label
        String startLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, startLabel));

        String endLabel = paraGenerate.nextLabel();
        //将forID加入到符号表中
        paraMap.putVariable(forId, new SymbolNode(forId, left, false, 0));
        TypeExpression right = (TypeExpression) visit(ctx.expression(1));
        //获取结束值
        Object endObj = expressionStack.pop();
        String notSuit = paraGenerate.nextPara();
        //判断是否应该终止循环
        if (isUp) {
            midCode.addNewCode(new MidCodeNode(OperationEnum.GREATER, forId, endObj, notSuit));
        } else {
            midCode.addNewCode(new MidCodeNode(OperationEnum.LESS, forId, endObj, notSuit));
        }
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, notSuit, endLabel));
        // 对upDown两侧的表达式的判断
        if (left.typeEquals(BaseTypeEnum.REAL) || right.typeEquals(BaseTypeEnum.REAL)) {
            //  错误流，实数
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ASSIGNOP().getSymbol().getLine() + 1;
            String tips = "实数类型无法当做范围";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
            resultType = new TypeExpression(ToolTypeEnum.ERROR);
        } else if (left.getTypeNode() instanceof TypeConstructor || right.getTypeNode() instanceof TypeConstructor) {
            //  错误流，构造类型没法当做范围
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ASSIGNOP().getSymbol().getCharPositionInLine() + 1;
            String tips = "构造类型无法当做范围";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
            resultType = new TypeExpression(ToolTypeEnum.ERROR);
        }
        //遍历表达式
        TypeExpression staType = (TypeExpression) visit(ctx.statement());
        //
        if (isUp)
            midCode.addNewCode(new MidCodeNode(OperationEnum.ADD, forId, 1, forId));
        else
            midCode.addNewCode(new MidCodeNode(OperationEnum.SUB, forId, 1, forId));
        //跳转到开头处
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, startLabel));
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, endLabel));
        //重定位
        paraMap.relocation();
        if (resultType == null) {
            log.logger("退出visitForStatement方法", 1);
            return new TypeExpression(ToolTypeEnum.VOID);
        }
        log.logger("退出visitForStatement方法", 1);
        return resultType;
    }

    /*
        对数组或者对记录的嵌套访问
        在Pascal中，数组的下标可以是任意标量类型（小数除外）
        也可以为负值
     */
    @Override
    public TypeExpression visitGetIDVarPartList(CalcParser.GetIDVarPartListContext ctx) {
        //  访问是递归的，想到的解决方案大概是加个Queue，在内部访问的时候每次都逐层的新建变量压入队列
        // 在返回之后外部再逐层产生三地址代码，以此达到目的
        // 三地址代码产生，难点
        log.logger("进入visitGetIDVarPartList方法", 1);
        //  对数组或者对记录的嵌套访问
        TypeExpression finalType = null;
        String variableName = ctx.ID().getText();
        TypeNode depNode = null;
        if (paraMap.containsVariable(variableName)) {
            TypeExpression varType = paraMap.getVariable(variableName).getSymbolType();
            // 复杂的类型检查
            //实际的参数，将对数组或域的访问区分开
            LinkedList<TypeExpression> paraType = (LinkedList<TypeExpression>) visit(ctx.id_varparts());

            String nowDepthName = variableName;
            for (String sigIDVar : expressionQueue) {
                String newDepthName = paraGenerate.nextPara();
                if (sigIDVar.charAt(0) == '.') {
                    //对域的访问
                    midCode.addNewCode(new MidCodeNode(OperationEnum.FILED, nowDepthName, sigIDVar.substring(1), newDepthName));
                    nowDepthName = newDepthName;
                    idVarQueue.add(new VarListAccess(true, sigIDVar.substring(1)));
                } else {
                    //对数组的访问
                    midCode.addNewCode(new MidCodeNode(OperationEnum.INDEX, nowDepthName, sigIDVar, newDepthName));
                    nowDepthName = newDepthName;
                    idVarQueue.add(new VarListAccess(false, sigIDVar));
                }
            }
            //对这个队列清空
            expressionQueue.clear();
            //最终的值
            expressionStack.push(nowDepthName);
            depNode = varType.getTypeNode();

            //这才是主循环，type表示访问链元素的类型表达式
            for (TypeExpression type : paraType) {
                //实际参数中的类型
                TypeConstructor realTypeCons = (TypeConstructor) type.getTypeNode();
                TypeConstructor varTypeCons = (TypeConstructor) depNode;
                if (realTypeCons.getType() == TypeConstructorEnum.RECOR) {
                    //对域的访问
                    if (varTypeCons.getType() != TypeConstructorEnum.RECOR) {
                        // 类型不匹配，错误流
                        int line = ctx.ID().getSymbol().getLine();
                        int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
                        String tips = "参数类型不匹配，请检查调用语句";
                        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                        finalType = new TypeExpression(ToolTypeEnum.ERROR);
                        break;
                    } else {
                        //记录内部域的名称
                        String recordName = ((ParaName) realTypeCons.getSonList().get(0)).getParaName();
                        ArrayList<TypeNode> sonList = varTypeCons.getSonList();
                        for (TypeNode nowTypeNode : sonList) {
                            TypeConstructor nowTypeCons = (TypeConstructor) nowTypeNode;
                            TypeNode nameStringNode = nowTypeCons.getSonList().get(0);

                            String name = ((ParaName) nameStringNode).getParaName();
                            if (name.equals(recordName)) {
                                //深入
                                depNode = nowTypeCons.getSonList().get(1);
                                break;
                            }
                        }
                    }
                } else if (realTypeCons.getType() == TypeConstructorEnum.ARRAY) {
                    //对数组的访问
                    // TODO: 2022-03-17 判断到末尾了怎么处理
                    if (varTypeCons.getType() != TypeConstructorEnum.ARRAY) {
                        // 类型不匹配，错误流
                        int line = ctx.ID().getSymbol().getLine();
                        int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
                        String tips = "参数类型不匹配，请检查调用语句";
                        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                        finalType = new TypeExpression(ToolTypeEnum.ERROR);
                    } else {
                        if (varTypeCons.getArrayDepth() != type.getArrayDepth()) {
                            // 数组维度不匹配 错误流
                            int line = ctx.ID().getSymbol().getLine();
                            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
                            String tips = "数组维数不匹配，请检查调用语句";
                            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                            finalType = new TypeExpression(ToolTypeEnum.ERROR);
                        } else {
                            int arrayDepth = varTypeCons.getArrayDepth();
                            for (int i = 0; i < arrayDepth; i++) {
                                //逐层深入
                                depNode = ((TypeConstructor) depNode).getSonList().get(0);
                            }
                            if (!(depNode instanceof TypeConstructor)) {
                                //已经抵达根节点
                                log.logger("退出visitGetIDVarPartList方法", 1);
                                return new TypeExpression(depNode);
                            }
                        }
                    }
                } else {
                    // 错误流，出现了ERROR类型
                    int line = ctx.ID().getSymbol().getLine();
                    int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
                    String tips = "变量参数错误";
                    errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
                    finalType = new TypeExpression(ToolTypeEnum.ERROR);
                }
            }
        } else {
            // 变量未定义
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "变量：'" + ctx.ID().getText() + "'未定义";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            finalType = new TypeExpression(ToolTypeEnum.ERROR);
        }
        if (finalType == null || !finalType.typeEquals(ToolTypeEnum.ERROR)) {
            finalType = new TypeExpression(depNode);
        }
        log.logger("退出visitGetIDVarPartList方法", 1);
        return finalType;
    }

    /*
        单个ID组成的变量，无嵌套
     */
    @Override
    public TypeExpression visitGetSigID(CalcParser.GetSigIDContext ctx) {
        log.logger("进入visitGetSigID方法", 1);
        String idVar = ctx.ID().getText();
        if (paraMap.containsVariable(idVar)) {
            if (isLeftValue) {
                if (paraMap.getVariable(idVar).isConst()) {
                    // 常数不能作为左值
                    int line = ctx.ID().getSymbol().getLine();
                    int inLine = ctx.ID().getSymbol().getCharPositionInLine();
                    String tips = "变量:'" + idVar + "'不能作为左值被赋值";
                    errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                    return new TypeExpression(ToolTypeEnum.ERROR);
                }
            }
            expressionStack.push(idVar);
            log.logger("退出visitGetSigID方法", 1);
            return paraMap.getVariable(idVar).getSymbolType();
        } else {
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "变量'" + idVar + "'未定义";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            log.logger("退出visitGetSigID方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        嵌套变量
        多维数组的访问，[1,2]表示访问第2行的第3列，依次类推
        语法：id_varparts id_varpart
     */
    @Override
    public LinkedList<TypeExpression> visitGetIDVarList(CalcParser.GetIDVarListContext ctx) {
        log.logger("进入visitGetIDVarList方法", 1);
        // 嵌套变量多维数组的访问
        LinkedList<TypeExpression> idVarList = new LinkedList<>();
        idVarList.addAll((LinkedList<TypeExpression>) visit(ctx.id_varparts()));
        idVarList.add((TypeExpression) visit(ctx.id_varpart()));
        log.logger("退出visitGetIDVarList方法", 1);
        return idVarList;
    }

    /*
        单个ID的变量
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigIDVar(CalcParser.GetSigIDVarContext ctx) {
        log.logger("进入visitGetSigIDVar方法", 1);
        // 单个ID的访问
        TypeExpression sigIdVar = (TypeExpression) visit(ctx.id_varpart());
        LinkedList<TypeExpression> sigList = new LinkedList<>();
        sigList.add(sigIdVar);
        log.logger("退出visitGetSigIDVar方法", 1);
        return sigList;
    }

    /*
        数组中的一部分
        语法：LEFT_BRACKET expression_list RIGHT_BRACKET
        用中括号括起来的表达式列表
     */
    @Override
    public TypeExpression visitExpID(CalcParser.ExpIDContext ctx) {
        log.logger("进入visitExpID方法", 1);
        LinkedList<TypeExpression> expList = (LinkedList<TypeExpression>) visit(ctx.expression_list());

        //现在还不能确定数组内部的类型，填void
        ArrayList<TypeNode> nullSon = new ArrayList<>(1);
        nullSon.add(ToolTypeEnum.VOID);
        TypeConstructor headType = null;
        TypeConstructor currType = null;
        int nestDepth = 0;
        for (TypeExpression type : expList) {
            if (!(type.typeEquals(BaseTypeEnum.INTEGER)
                    || type.typeEquals(BaseTypeEnum.BOOLEAN)
                    || type.typeEquals(BaseTypeEnum.REAL))) {
                //  错误流
                int line = ctx.LEFT_BRACKET().getSymbol().getLine();
                int inLine = ctx.LEFT_BRACKET().getSymbol().getCharPositionInLine() + 1;
                String tips = "数组下标类型错误，请检查声明语句";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
                log.logger("退出visitExpID方法", 1);
                return new TypeExpression(ToolTypeEnum.ERROR);
            } else {
                nestDepth++;
                if (headType == null) {
                    headType = new TypeConstructor(TypeConstructorEnum.ARRAY, null, nestDepth);
                    currType = headType;
                } else {
                    currType.addNewSon(new TypeConstructor(TypeConstructorEnum.ARRAY, null, nestDepth));
                    currType = (TypeConstructor) currType.getSonList().get(0);
                }
            }
        }
        log.logger("退出visitExpID方法", 1);
        return new TypeExpression(headType);
    }

    /*
        这个域的成员
        用.来访问的，类似Java中的成员变量
     */
    @Override
    public TypeExpression visitFieldID(CalcParser.FieldIDContext ctx) {
        log.logger("进入visitFieldID方法", 1);
        //这里把域的访问当做记录来封装，只包含一个son
        ArrayList<TypeNode> idNode = new ArrayList<>(1);
        idNode.add(new ParaName(ctx.ID().getText()));
        expressionQueue.add("." + ctx.ID().getText());
        log.logger("退出visitFieldID方法", 1);
        return new TypeExpression(new TypeConstructor(TypeConstructorEnum.RECOR, idNode));
    }

    /*
        elsePart
        包含语句
        语法：ELSE statement
     */
    @Override
    public TypeExpression visitElsePart(CalcParser.ElsePartContext ctx) {
        log.logger("进入visitElsePart方法", 1);
        TypeExpression elseType = (TypeExpression) visit(ctx.statement());
        log.logger("退出visitElsePart方法", 1);
        return elseType;
    }

    /*
        caseBody
        有或者没有分支结构
     */
    @Override
    public TypeExpression visitGetBranchBody(CalcParser.GetBranchBodyContext ctx) {
        log.logger("进入visitGetBranchBody方法", 1);
        // caseBody语句
        //直接返回分支语句类型表达式
        if (ctx.branch_list() != null) {
            TypeExpression branchType = (TypeExpression) visit(ctx.branch_list());
            log.logger("退出visitGetBranchBody方法", 1);
            return branchType;
        } else {
            log.logger("退出visitGetBranchBody方法", 1);
            return new TypeExpression(ToolTypeEnum.VOID);
        }
    }

    /*
        单个分支
        只不过是在分支列表里的
     */
    @Override
    public TypeExpression visitGetSigBranch(CalcParser.GetSigBranchContext ctx) {
        // 单个分支
        log.logger("进入visitGetSigBranch方法", 1);
        TypeExpression sigBranchType = (TypeExpression) visit(ctx.branch());
        log.logger("退出visitGetSigBranch方法", 1);
        return sigBranchType;
    }

    /*
        多个分支的列表
        用分号分开
        语法：branch_list SEMICOLON branch

     */
    @Override
    public TypeExpression visitGetBranchList(CalcParser.GetBranchListContext ctx) {
        // 多个分支的列表
        log.logger("进入visitGetBranchList方法", 1);
        //这里做了个递归的类型检查
        TypeExpression branchType = (TypeExpression) visit(ctx.branch_list());
        TypeExpression sigType = (TypeExpression) visit(ctx.branch());
        if (branchType.typeEquals(sigType) && !branchType.typeEquals(ToolTypeEnum.ERROR)) {
            log.logger("退出visitGetBranchList方法", 1);
            return branchType;
        } else {
            log.logger("退出visitGetBranchList方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        单个分支
        判断CASE的值是不是和常量表中的匹配
        里面包含语句
        语法：const_list COLON statement
     */
    @Override
    public TypeExpression visitSigBranch(CalcParser.SigBranchContext ctx) {
        log.logger("进入visitSigBranch方法", 1);
        // 包含语句的分支
        LinkedList<TypeExpression> constTypeList = (LinkedList<TypeExpression>) visit(ctx.const_list());

        String label = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.LABEL, label));

        TypeExpression staType = (TypeExpression) visit(ctx.statement());
        Object expObj = caseExpStack.peek();
        String nextLabel = paraGenerate.nextLabel();
        midCode.addNewCode(new MidCodeNode(OperationEnum.GOTO, nextLabel));
        int size = constTypeList.size();
        TypeExpression firstType = constTypeList.getFirst();
        for (TypeExpression type : constTypeList) {
            if (!type.typeEquals(firstType)) {
                // 类型不匹配，错误流
                int line = ctx.COLON().getSymbol().getLine();
                int inLine = ctx.COLON().getSymbol().getCharPositionInLine() - 1;
                String tips = "判断语句类型不匹配，请检查case语句";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.MISMATCH, tips));
                log.logger("退出visitSigBranch方法", 1);
                return new TypeExpression(ToolTypeEnum.ERROR);
            }
            Object nowValue = branchConstList.pollFirst();

            caseNodeList.add(new MidCodeNode(OperationEnum.EQUAL, nowValue, expObj, label));
        }
        caseNodeList.add(new MidCodeNode(OperationEnum.LABEL, nextLabel));
        log.logger("退出visitSigBranch方法", 1);
        return firstType;
    }

    /*
        常量列表
        语法：const_list COMMA const_variable
     */
    @Override
    public LinkedList<TypeExpression> visitGetConstList(CalcParser.GetConstListContext ctx) {
        log.logger("进入visitGetConstList方法", 1);
        LinkedList<TypeExpression> constList = (LinkedList<TypeExpression>) visit(ctx.const_list());
        constList.add((TypeExpression) visit(ctx.const_variable()));
        // 拿取常数
        Object constObj = expressionStack.pop();
        branchConstList.add(constObj);
        log.logger("退出visitGetConstList方法", 1);
        return constList;
    }

    /*
        单个常量，如果是ID则要做标识符检测
        语法：const_variable
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigConst(CalcParser.GetSigConstContext ctx) {
        log.logger("进入visitGetSigConst方法", 1);
        LinkedList<TypeExpression> sigType = new LinkedList<>();
        sigType.add((TypeExpression) visit(ctx.const_variable()));
        // 拿取常数
        Object constObj = expressionStack.pop();
        branchConstList.add(constObj);
        log.logger("退出visitGetSigConst方法", 1);
        return sigType;
    }

    /*
        to/downTo的一个判断
        返回boolean就行？
     */
    @Override
    public Boolean visitUpdown(CalcParser.UpdownContext ctx) {
        log.logger("进入visitUpdown方法", 1);
        if (ctx.getText().equals("to")) {
            log.logger("退出visitUpdown方法", 1);
            return true;
        }
        log.logger("退出visitUpdown方法", 1);
        return false;
    }

    /*
        过程调用，无参数的
     */
    @Override
    public TypeExpression visitGetPro(CalcParser.GetProContext ctx) {
        log.logger("进入visitGetPro方法", 1);
        String proName = ctx.ID().getText();
        if (paraMap.containsFunction(proName)) {
            // 无参调用，写入三地址代码
            midCode.addNewCode(new MidCodeNode(OperationEnum.CALL, proName, 0));
        } else {
            //  加入到错误流
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "过程未定义，请检查调用语句";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            log.logger("退出visitGetPro方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitGetPro方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        过程调用
        这个是带参数的，放在参数表里
        注意对这个做检查
        语法：ID LEFT_BRA expression_list RIGHT_BRA
     */
    @Override
    public TypeExpression visitGetFunc(CalcParser.GetFuncContext ctx) {
        log.logger("进入visitGetFunc方法", 1);
        String funcName = ctx.ID().getText();
        if (!paraMap.containsFunction(funcName)) {
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "函数未定义，请检查调用语句";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            log.logger("退出visitGetFunc方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        LinkedList<TypeExpression> expList = (LinkedList<TypeExpression>) visit(ctx.expression_list());
        int paraSize = expressionQueue.size();
        HashSet<Integer> referIndexSet = paraMap.getFunction(funcName).getReferIndex();
        for (int i = paraSize - 1; i >= 0; i--) {
            if (referIndexSet.contains(i)) {
                midCode.addNewCode(new MidCodeNode(OperationEnum.PARA_REFER, expressionQueue.pollLast()));
            } else {
                midCode.addNewCode(new MidCodeNode(OperationEnum.PARA, expressionQueue.pollLast()));
            }
        }
//        String returnValue = paraGenerate.nextPara();
        midCode.addNewCode(new MidCodeNode(OperationEnum.CALL, funcName));
//        expressionStack.push(returnValue);

        int line = ctx.ID().getSymbol().getLine();
        int inLine = ctx.ID().getSymbol().getCharPositionInLine();
        //类型检查
        TypeExpression resultType = typeCheck.funcTypeCheck(funcName, expList, line, inLine);
        log.logger("退出visitGetFunc方法", 1);
        return resultType;
    }

    /*
        多个用,分割开的表达式
        语法：expression_list COMMA expression
     */
    //测试14.1<19+1.1,193,'a'通过
    @Override
    public LinkedList<TypeExpression> visitGetExpList(CalcParser.GetExpListContext ctx) {
        log.logger("进入visitGetExpList方法", 1);
        LinkedList<TypeExpression> innerList = (LinkedList<TypeExpression>) visit(ctx.expression_list());
        innerList.add((TypeExpression) visit(ctx.expression()));
        expressionQueue.add(expressionStack.pop().toString());
        log.logger("退出visitGetExpList方法", 1);
        return innerList;
    }

    /*
        单个表达式
     */
    @Override
    public LinkedList<TypeExpression> visitGetSigExp(CalcParser.GetSigExpContext ctx) {
        log.logger("进入visitGetSigExp方法", 1);
        LinkedList<TypeExpression> sigResult = new LinkedList<>();
        sigResult.add((TypeExpression) visit(ctx.expression()));
        expressionQueue.add(expressionStack.pop().toString());
        log.logger("退出visitGetSigExp方法", 1);
        return sigResult;
    }

    /*
        多个表达式用关系运算符连起来
        语法：simple_expression (EQUAL|RELOP) simple_expression
     */
    @Override
    public TypeExpression visitRelopSimExp(CalcParser.RelopSimExpContext ctx) {
        log.logger("进入visitRelopSimExp方法", 1);
        TypeExpression leftType = (TypeExpression) visit(ctx.simple_expression(0));
        //获取栈中的计算结果
        Object leftObj = expressionStack.pop();
        TypeExpression rightType = (TypeExpression) visit(ctx.simple_expression(1));
        //获取栈中的计算结果
        Object rightObj = expressionStack.pop();
        //获取操作类型
        OperationEnum op;
        if (ctx.EQUAL() != null) {
            op = OperationEnum.EQUAL;
        } else {
            String opString = ctx.RELOP().getText();
            op = operateLocate(opString);
        }
        //添加到三地址代码中
        String resultObj = paraGenerate.nextPara();
        midCode.addNewCode(new MidCodeNode(op, leftObj, rightObj, resultObj));
        expressionStack.push(resultObj);

        TypeExpression resultType;
        if (leftType.typeEquals(rightType.getTypeNode()) && !leftType.typeEquals(ToolTypeEnum.ERROR)) {
            resultType = new TypeExpression(BaseTypeEnum.BOOLEAN);
        } else {
            resultType = new TypeExpression(ToolTypeEnum.ERROR);
        }
        log.logger("退出visitRelopSimExp方法", 1);
        return resultType;
    }

    /*
        单个表达式
     */
    @Override
    public TypeExpression visitSigSimExp(CalcParser.SigSimExpContext ctx) {
        log.logger("进入visitSigSimExp方法", 1);
        TypeExpression sigSimType = (TypeExpression) visit(ctx.simple_expression());
        log.logger("退出visitSigSimExp方法", 1);
        return sigSimType;
    }

    /*
        单独一个项
     */
    @Override
    public TypeExpression visitSigTerm(CalcParser.SigTermContext ctx) {
        log.logger("进入visitSigTerm方法", 1);
        //就一个term，直接递归即可
        TypeExpression sigTerm = (TypeExpression) visit(ctx.term());
        log.logger("退出visitSigTerm方法", 1);
        return sigTerm;
    }

    /*
        嵌套的项
        语法：simple_expression (OR|ADD|SUB) term
     */
    @Override
    public TypeExpression visitSimTerm(CalcParser.SimTermContext ctx) {
        log.logger("进入visitSimTerm方法", 1);
        //依次递归返回检查
        //这个是递归返回后的类型
        TypeExpression innerType = (TypeExpression) visit(ctx.simple_expression());
        Object innerObj = expressionStack.pop();
        //这里做类型检查
        TypeExpression outerType = (TypeExpression) visit(ctx.term());
        Object outerObj = expressionStack.pop();

        TypeExpression resultType;
        if (ctx.OR() != null) {
            //或OR
            if (innerType.typeEquals(BaseTypeEnum.BOOLEAN) && outerType.typeEquals(BaseTypeEnum.BOOLEAN)) {
                //产生合规的三地址代码
                String resultPara = paraGenerate.nextPara();
                midCode.addNewCode(new MidCodeNode(OperationEnum.OR, innerObj, outerObj, resultPara));
                expressionStack.push(resultPara);
                resultType = new TypeExpression(BaseTypeEnum.BOOLEAN);
            } else {
                resultType = new TypeExpression(ToolTypeEnum.ERROR);
            }
        } else {
            //加或减
            resultType = typeCheck.checkOpType(innerType, outerType);
            OperationEnum op;
            if (!resultType.typeEquals(ToolTypeEnum.ERROR)) {
                //判断操作类型
                if (ctx.ADD() != null) {
                    op = OperationEnum.ADD;
                } else {
                    op = OperationEnum.SUB;
                }
                String resultPara = paraGenerate.nextPara();
                midCode.addNewCode(new MidCodeNode(op, innerObj, outerObj, resultPara));
                expressionStack.push(resultPara);
            }
        }
        log.logger("退出visitSimTerm方法", 1);
        return resultType;
    }

    /*
        加上一个项
        语法：ADD term
     */
    @Override
    public TypeExpression visitAddTerm(CalcParser.AddTermContext ctx) {
        log.logger("进入visitAddTerm方法", 1);
        TypeExpression addTerm = (TypeExpression) visit(ctx.term());
        log.logger("退出visitAddTerm方法", 1);
        return addTerm;
    }

    /*
        减去一个项
        语法：SUB term
     */
    @Override
    public TypeExpression visitSubTerm(CalcParser.SubTermContext ctx) {
        log.logger("进入visitSubTerm方法", 1);
        TypeExpression addTerm = (TypeExpression) visit(ctx.term());
        Object termExp = expressionStack.pop();
        String minusPara = paraGenerate.nextPara();
        //取负数
        midCode.addNewCode(new MidCodeNode(OperationEnum.MINUS, termExp, minusPara));
        expressionStack.push(minusPara);
        log.logger("退出visitSubTerm方法", 1);
        return addTerm;
    }

    /*
        读取项里的单个因子
        直接就是一个factor
     */
    @Override
    public TypeExpression visitSigFactor(CalcParser.SigFactorContext ctx) {
        log.logger("进入visitSigFactor方法", 1);
        TypeExpression sigFactor = (TypeExpression) visit(ctx.factor());
        log.logger("退出visitSigFactor方法", 1);
        return sigFactor;
    }

    /*
        读取项中的多个因子
        注意还有运算符
        语法：term MULOP factor
     */
    @Override
    public TypeExpression visitMultiFactor(CalcParser.MultiFactorContext ctx) {
        log.logger("进入visitMultiFactor方法", 1);
        TypeExpression innerType = (TypeExpression) visit(ctx.term());
        Object innerObj = expressionStack.pop();
        TypeExpression outerType = (TypeExpression) visit(ctx.factor());
        Object outerObj = expressionStack.pop();
        TypeExpression resultType = null;
        switch (ctx.MULOP().getText()) {
            case "*": {
                resultType = typeCheck.checkOpType(innerType, outerType);
                if (!resultType.typeEquals(ToolTypeEnum.ERROR)) {
                    String resultPara = paraGenerate.nextPara();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.MULTI, innerObj, outerObj, resultPara));
                    expressionStack.push(resultPara);
                }
                break;
            }
            case "/":
            case "div": {
                resultType = typeCheck.checkOpType(innerType, outerType);
                // TODO: 2022-03-21 检查除数不为0
                if (!resultType.typeEquals(ToolTypeEnum.ERROR)) {
                    String resultPara = paraGenerate.nextPara();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.DIV, innerObj, outerObj, resultPara));
                    expressionStack.push(resultPara);
                }
                break;
            }
            case "mod":
                if (innerType.typeEquals(BaseTypeEnum.INTEGER) && outerType.typeEquals(BaseTypeEnum.INTEGER)) {
                    String resultPara = paraGenerate.nextPara();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.MOD, innerObj, outerObj, resultPara));
                    expressionStack.push(resultPara);
                    resultType = new TypeExpression(BaseTypeEnum.INTEGER);
                } else {
                    resultType = new TypeExpression(ToolTypeEnum.ERROR);
                }
                break;
            case "and":
                if (innerType.typeEquals(BaseTypeEnum.BOOLEAN) && outerType.typeEquals(BaseTypeEnum.BOOLEAN)) {
                    String resultPara = paraGenerate.nextPara();
                    midCode.addNewCode(new MidCodeNode(OperationEnum.AND, innerObj, outerObj, resultPara));
                    expressionStack.push(resultPara);
                    resultType = new TypeExpression(BaseTypeEnum.BOOLEAN);
                } else {
                    resultType = new TypeExpression(ToolTypeEnum.ERROR);
                }
                break;
        }
        log.logger("退出visitMultiFactor方法", 1);
        return resultType;
    }

    /*
        读取常量做因子
        如果是ID的话需要检查符号表
        语法：factor：unsign_const_variable
     */
    @Override
    public TypeExpression visitUcvFactor(CalcParser.UcvFactorContext ctx) {
        log.logger("进入visitUcvFactor方法", 1);
        TypeExpression ucvType = (TypeExpression) visit(ctx.unsign_const_variable());
        log.logger("退出visitUcvFactor方法", 1);
        return ucvType;
    }

    /*
        直接读取变量当做因子
        语法：factor：variable
     */
    @Override
    public TypeExpression visitVarFactor(CalcParser.VarFactorContext ctx) {
        log.logger("进入visitVarFactor方法", 1);
        //变量是一个很复杂的东西，可以是变量标识符、数组、记录，需要做区分
        //在variable里已经压入了expressionStack
        TypeExpression factorType = (TypeExpression) visit(ctx.variable());
        log.logger("退出visitVarFactor方法", 1);
        return factorType;
    }

    /*
        读取函数调用
        函数也需要读取函数表看能不能调用这个函数
        同时还需要对表达式的参数做检查
        语法：ID LEFT_BRA expression_list RIGHT_BRA
     */
    @Override
    public TypeExpression visitFuncFactor(CalcParser.FuncFactorContext ctx) {
        log.logger("进入visitFuncFactor方法", 1);
        String funcName = ctx.ID().getText();
        LinkedList<TypeExpression> expList = (LinkedList) visit(ctx.expression_list());
        int line = ctx.ID().getSymbol().getLine();
        int inLine = ctx.ID().getSymbol().getCharPositionInLine();
        TypeExpression resultType = typeCheck.funcTypeCheck(funcName, expList, line, inLine);
        if (!resultType.typeEquals(ToolTypeEnum.ERROR)) {
            int size = expressionQueue.size();
            //引用传递的参数的下标
            HashSet<Integer> referIndexSet = paraMap.getFunction(funcName).getReferIndex();
            for (int i = size - 1; i >= 0; i--) {
                if (referIndexSet.contains(i)) {
                    midCode.addNewCode(new MidCodeNode(OperationEnum.PARA_REFER, expressionQueue.pollLast()));
                } else {
                    midCode.addNewCode(new MidCodeNode(OperationEnum.PARA, expressionQueue.pollLast()));
                }
            }
        }
        String result = paraGenerate.nextPara();
        midCode.addNewCode(new MidCodeNode(OperationEnum.CALL, funcName, result));
        expressionStack.push(result);
        log.logger("退出visitFuncFactor方法", 1);
        return resultType;
    }

    /*
        读取被括号包裹起来的表达式
        语法：LEFT_BRA expression_list RIGHT_BRA
     */
    @Override
    public TypeExpression visitExpFactor(CalcParser.ExpFactorContext ctx) {
        log.logger("进入visitExpFactor方法", 1);
        TypeExpression expType = (TypeExpression) visit(ctx.expression());
        log.logger("退出visitExpFactor方法", 1);
        return expType;
    }

    /*
        读取not 因子
        语法：NOT factor
     */
    @Override
    public TypeExpression visitNotFactor(CalcParser.NotFactorContext ctx) {
        log.logger("进入visitNotFactor方法", 1);
        TypeExpression notFactor = (TypeExpression) visit(ctx.factor());
        Object factorObj = expressionStack.pop();
        if (!notFactor.typeEquals(BaseTypeEnum.BOOLEAN)) {
            int line = ctx.NOT().getSymbol().getLine();
            int inLine = ctx.NOT().getSymbol().getCharPositionInLine() + 1;
            String tips = "类型:'" + ctx.factor().getText() + "'不为布尔值，无法进行取反操作，请检查表达式";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.ERROR_TYPE, tips));
        } else {
            String resultPara = paraGenerate.nextPara();
            midCode.addNewCode(new MidCodeNode(OperationEnum.NOT, factorObj, resultPara));
            expressionStack.push(resultPara);
        }
        log.logger("退出visitNotFactor方法", 1);
        return notFactor;
    }

    /*
        读取标识符
        直接就是unsign_const_variable：ID
     */
    @Override
    public TypeExpression visitUnsignConstVariableID(CalcParser.UnsignConstVariableIDContext ctx) {
        log.logger("进入visitUnsignConstVariableID方法", 1);
        String ucvID = ctx.ID().getText();
        if (paraMap.containsVariable(ucvID)) {
            log.logger("退出visitUnsignConstVariableID方法", 1);
            expressionStack.push(ucvID);
            return paraMap.getVariable(ucvID).getSymbolType();
        } else {
            //  增加到错误流中
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "变量未定义";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            log.logger("退出visitUnsignConstVariableID方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
    }

    /*
        读取数字
        返回给上级
        unsign_const_variable：NUM
     */
    @Override
    public TypeExpression visitUnsignConstVariableNum(CalcParser.UnsignConstVariableNumContext ctx) {
        log.logger("进入visitUnsignConstVariableNum方法", 1);
        if (ctx.NUM().getText().contains(".")) {
            expressionStack.push(Double.parseDouble(ctx.NUM().getText()));
            log.logger("退出visitUnsignConstVariableNum方法", 1);
            return new TypeExpression(BaseTypeEnum.REAL);
        } else {
            expressionStack.push(Integer.parseInt(ctx.NUM().getText()));
            log.logger("退出visitUnsignConstVariableNum方法", 1);
            return new TypeExpression(BaseTypeEnum.INTEGER);
        }
    }

    /*
        读取单个字符
        返回给上级
        unsign_const_variable：SIG_QUT LETTER SIG_QUT
     */
    @Override
    public TypeExpression visitUnsignConstVariableLetter(CalcParser.UnsignConstVariableLetterContext ctx) {
        log.logger("进入visitUnsignConstVariableLetter方法", 1);
        //'a'
        expressionStack.push(ctx.getText());
        log.logger("退出visitUnsignConstVariableLetter方法", 1);
        return new TypeExpression(BaseTypeEnum.CHAR);
    }

    @Override
    public TypeExpression visitUnsignConstVariableBoolean(CalcParser.UnsignConstVariableBooleanContext ctx) {
        // 布尔值常量的获取
        log.logger("进入visitUnsignConstVariableBoolean方法", 1);
        TypeExpression booleanType = (TypeExpression) visit(ctx.booleanEnum());
        log.logger("退出visitUnsignConstVariableBoolean方法", 1);
        return booleanType;
    }

    /*
        read函数对应的方法
        在这里面要读入键盘输入到变量
        所以要读取符号表相关，检查这个变量是不是可访问
     */
    @Override
    public TypeExpression visitReadSomePara(CalcParser.ReadSomeParaContext ctx) {
        log.logger("进入visitReadSomePara方法", 1);
        ArrayList<String> readVarList = (ArrayList<String>) visit(ctx.para_table_read());

        if (readVarList == null) {
            log.logger("退出visitReadSomePara方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        for (String read : readVarList) {
            // 为每个读取变量产生三地址代码
            midCode.addNewCode(new MidCodeNode(OperationEnum.READ, read));
        }
        log.logger("退出visitReadSomePara方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        write函数对应的方法
        将变量或者被‘包裹的内容打印出来
        同样要访问符号表
     */
    @Override
    public TypeExpression visitWriteSomePara(CalcParser.WriteSomeParaContext ctx) {
        log.logger("进入visitWriteSomePara方法", 1);
        ArrayList<String> writeList = (ArrayList<String>) visit(ctx.para_table_write());
        if (writeList == null) {
            log.logger("退出visitWriteSomePara方法", 1);
            return new TypeExpression(ToolTypeEnum.ERROR);
        }
        for (String output : writeList) {
            //如果输出的是字符串
            if (output.charAt(0) == '_') {
                midCode.addNewCode(new MidCodeNode(OperationEnum.WRITE, output.substring(1)));
            } else {
                //输出的是变量的情况
                // TODO: 2022-03-21 根据变量的类型不同对变量做遍历
                TypeExpression varType = paraMap.getVariable(output).getSymbolType();
                //基本数据类型
                TypeNode rootTypeNode = varType.getTypeNode();
                if (rootTypeNode instanceof BaseTypeEnum) {
                    midCode.addNewCode(new MidCodeNode(OperationEnum.WRITE, output));
                } else if (rootTypeNode instanceof TypeConstructor) {
                    // TODO: 2022-03-26 遍历复杂类型（数组、记录）以及其嵌套类型
                    // 按照树的格式来遍历，基本类型就直接输出，复杂类型就加入到STACK中，下一层遍历的时候再往复
                    // 还需要添加哑节点和上一层变量名的标识符
                    TypeConstructor rootTypeCons = (TypeConstructor) rootTypeNode;
                    Stack<TypeNode> outputTypeStack = new Stack<>();
                    Stack<String> tempVariableStack = new Stack<>();
                    String tempVariable = output;
                    tempVariableStack.push(tempVariable);
                    outputTypeStack.push(rootTypeCons);
                    while (!outputTypeStack.isEmpty()) {
                        // 这个node有三种可能，哑节点、构造器、数据节点
                        TypeNode nowNode = outputTypeStack.pop();
//                        if (nowNode instanceof DumbNode) {
//                            //哑节点，表示当前分支检索完毕，这个时候应该弹出temp变量
//                            tempVariableStack.pop();
//                        } else
                        if (nowNode instanceof VarListAccess) {
                            //数据节点，直接输出即可
                            String fatherName = tempVariableStack.pop();
                            String tempOutput = paraGenerate.nextPara();
                            VarListAccess nowVar = (VarListAccess) nowNode;
                            if (nowVar.isFiled()) {
                                midCode.addNewCode(new MidCodeNode(OperationEnum.FILED, fatherName, nowVar.getFiledOrIndex(), tempOutput));
                            } else {
                                midCode.addNewCode(new MidCodeNode(OperationEnum.INDEX, fatherName, nowVar.getFiledOrIndex(), tempOutput));
                            }
                            midCode.addNewCode(new MidCodeNode(OperationEnum.WRITE, tempOutput));
                        } else {
                            // 构造器
                            TypeConstructor nowCons = (TypeConstructor) nowNode;
                            if (nowCons.getType() == TypeConstructorEnum.ARRAY) {
                                //数组的情况
//                                tempVariableStack.push(tempVariable);
                                ArrayList<TypeNode> sonList = nowCons.getSonList();
                                ArrayRange arrayRange = (ArrayRange) sonList.get(1);
                                TypeNode innerType = sonList.get(0);
                                tempVariable = tempVariableStack.pop();
                                if (innerType instanceof BaseTypeEnum) {
                                    //基本数据类型，压入到栈中留之后输出
                                    if (arrayRange.isInt()) {
                                        //如果数组下标是整数的情况
                                        int end = (int) arrayRange.getEnd();
                                        int start = (int) arrayRange.getStart();
                                        for (int nowIndex = end; nowIndex >= start; nowIndex--) {
                                            tempVariableStack.push(tempVariable);
                                            VarListAccess arrayEle = new VarListAccess(false, nowIndex + "");
                                            outputTypeStack.push(arrayEle);
                                        }
                                    } else {
                                        //如果数组下标是字符的情况
                                        char end = (char) arrayRange.getEnd();
                                        char start = (char) arrayRange.getStart();
                                        for (char nowIndex = end; nowIndex >= start; nowIndex--) {
                                            tempVariableStack.push(tempVariable);
                                            VarListAccess arrayEle = new VarListAccess(false, nowIndex + "");
                                            outputTypeStack.push(arrayEle);
                                        }
                                    }
                                } else {
                                    //这种情况表示这个数组是多维数组
                                    //无论是数组还是记录都压栈里，注意tempVariable的问题
                                    //这里需要把每个数组内元素的名字都给压到栈里
                                    TypeConstructor innerCons = (TypeConstructor) innerType;
//                                    outputTypeStack.push(new DumbNode());
                                    if (arrayRange.isInt()) {
                                        //如果数组下标是整数的情况
                                        int end = (int) arrayRange.getEnd();
                                        int start = (int) arrayRange.getStart();
                                        for (int nowIndex = end; nowIndex >= start; nowIndex--) {
                                            String nowEle = paraGenerate.nextPara();
                                            midCode.addNewCode(new MidCodeNode(OperationEnum.INDEX, tempVariable, nowIndex, nowEle));
                                            outputTypeStack.push(innerCons);
                                            tempVariableStack.push(nowEle);
                                        }
                                    } else {
                                        //如果数组下标是字符的情况
                                        char end = (char) arrayRange.getEnd();
                                        char start = (char) arrayRange.getStart();
                                        for (char nowIndex = end; nowIndex >= start; nowIndex--) {
                                            String nowEle = paraGenerate.nextPara();
                                            midCode.addNewCode(new MidCodeNode(OperationEnum.INDEX, tempVariable, nowIndex, nowEle));
                                            outputTypeStack.push(innerCons);
                                            tempVariableStack.push(nowEle);
                                        }
                                    }
                                }
                            } else {
                                //表示遇到了一个记录
                                ArrayList<TypeNode> recordSonList = nowCons.getSonList();
                                int sonSize = recordSonList.size();
                                String fatherName = tempVariableStack.peek();
                                //倒序判断节点类型并做相应处理
                                //先压一个哑结点
//                                outputTypeStack.push(new DumbNode());
                                for (int index = sonSize - 1; index >= 0; index--) {
                                    //记录内部的子类型一定是构造类型，所以直接强转成笛卡尔积的构造器
                                    TypeConstructor nowElement = (TypeConstructor) recordSonList.get(index);
                                    //这里就是看单个字段的内部是什么类型
                                    TypeNode innerType = nowElement.getSonList().get(1);
                                    String eleName = ((ParaName) nowElement.getSonList().get(0)).getParaName();
                                    if (innerType instanceof BaseTypeEnum) {
                                        // 基本类型，压栈
                                        VarListAccess nowEle = new VarListAccess(true, eleName);
                                        outputTypeStack.push(nowEle);
                                        tempVariableStack.push(fatherName);
                                    } else {
                                        //无论是数组还是记录都压栈里，注意tempVariable的问题
                                        String newRecord = paraGenerate.nextPara();
                                        midCode.addNewCode(new MidCodeNode(OperationEnum.FILED, fatherName, eleName, newRecord));
                                        tempVariableStack.push(newRecord);
                                        outputTypeStack.push(innerType);
                                    }
                                }

                            }
                        }
                    }
                }
            }
        }
        log.logger("退出visitWriteSomePara方法", 1);
        return new TypeExpression(ToolTypeEnum.VOID);
    }

    /*
        读取多个要read的变量
        将变量List返回到read去处理
        本身只负责读取变量
     */
    @Override
    public ArrayList<String> visitReadParaTable(CalcParser.ReadParaTableContext ctx) {
        log.logger("进入visitReadParaTable方法", 1);
        ArrayList<String> readVarList = new ArrayList<>();
        String readVar = ctx.ID().getText();
        if (paraMap.containsVariable(readVar)) {
            readVarList.add(readVar);
        } else {
            //  增加到报错流中
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "变量:'" + readVar + "'未定义";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
        }
        readVarList.addAll((ArrayList<String>) visit(ctx.para_table_read()));
        log.logger("退出visitReadParaTable方法", 1);
        return readVarList;
    }

    /*
        读取单个要read的变量
        同上，不做处理
     */
    @Override
    public ArrayList<String> visitReadPara(CalcParser.ReadParaContext ctx) {
        log.logger("进入visitReadPara方法", 1);
        String readVariable = ctx.ID().getText();
        if (paraMap.containsVariable(readVariable)) {
            ArrayList<String> sigList = new ArrayList<>(1);
            sigList.add(readVariable);
            log.logger("退出visitReadPara方法", 1);

            return sigList;
        }
        // 增加到报错流中
        int line = ctx.ID().getSymbol().getLine();
        int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
        String tips = "变量:'" + readVariable + "'未定义";
        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
        log.logger("退出visitReadPara方法", 1);
        return null;

    }

    /*
        读取多个要write的值（包含字符串）
        返回给write方法，本身不做处理
     */
    @Override
    public ArrayList<String> visitGetWriteParaTable(CalcParser.GetWriteParaTableContext ctx) {
        log.logger("进入visitGetWriteParaTable方法", 1);
        //将所有的输出：字符串、变量，都装到output中，字符串以下划线开头
        ArrayList<String> output = new ArrayList<>(2);
        if (ctx.ID() != null) {
            //变量输出
            String writeID = ctx.ID().getText();
            if (paraMap.containsVariable(writeID)) {
                output.add(writeID);
            } else {
                // 增加到报错流中
                int line = ctx.ID().getSymbol().getLine();
                int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
                String tips = "变量:'" + writeID + "'未定义";
                errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
            }
        } else {
            //字符串输出
            String originString = ctx.SIG_STRING().getText();
            output.add("_" + originString);
        }
        ArrayList<String> innerParaList = (ArrayList<String>) visit(ctx.para_table_write());
        output.addAll(innerParaList);
        log.logger("退出visitGetWriteParaTable方法", 1);
        return output;
    }


    /*
        读取单个ID值
     */
    @Override
    public ArrayList<String> visitGetWritePara(CalcParser.GetWriteParaContext ctx) {
        log.logger("进入visitGetWritePara方法", 1);
        String writeID = ctx.ID().getText();
        if (paraMap.containsVariable(writeID)) {
            ArrayList<String> result = new ArrayList<>(1);
            result.add(writeID);
            log.logger("退出visitGetWritePara方法", 1);
            return result;
        } else {
            //增加到报错流中
            int line = ctx.ID().getSymbol().getLine();
            int inLine = ctx.ID().getSymbol().getCharPositionInLine() + 1;
            String tips = "变量:'" + writeID + "'未定义";
            errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.UNDEFINE, tips));
        }
        log.logger("退出visitGetWritePara方法", 1);
        return null;
    }

    /*
        读取要输出的String
     */
    @Override
    public ArrayList<String> visitGetWriteString(CalcParser.GetWriteStringContext ctx) {
        log.logger("进入visitGetWriteString方法", 1);
        //返回write中得到的字符串
        ArrayList<String> writeString = new ArrayList<>(1);
        String outputString = ctx.getText();
        writeString.add("_" + outputString);
        log.logger("退出visitGetWriteString方法", 1);
        return writeString;
    }

    @Override
    public TypeExpression visitBooleanEnum(CalcParser.BooleanEnumContext ctx) {
        log.logger("进入visitBooleanEnum方法", 1);
        // 布尔值获取
        TypeExpression booleanType = new TypeExpression(BaseTypeEnum.BOOLEAN);
        expressionStack.push(ctx.getText());
        log.logger("退出visitBooleanEnum方法", 1);
        return booleanType;
    }

    private TypeExpression standTypeDetect(String standType) {
        TypeExpression standardType = null;
        switch (standType) {
            case "integer":
                standardType = new TypeExpression(BaseTypeEnum.INTEGER);
                break;
            case "real":
                standardType = new TypeExpression(BaseTypeEnum.REAL);
                break;
            case "boolean":
                standardType = new TypeExpression(BaseTypeEnum.BOOLEAN);
                break;
            case "char":
                standardType = new TypeExpression(BaseTypeEnum.CHAR);
                break;
        }
        return standardType;
    }

    private void redefineID(Token token) {
        int line = token.getLine();
        int inLine = token.getCharPositionInLine();
        String tips = "变量：'" + token.getText() + "'重复定义";
        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
    }

    private void undefineID(Token token) {
        int line = token.getLine();
        int inLine = token.getCharPositionInLine();
        String tips = "变量：'" + token.getText() + "'未定义";
        errorDeliver.addNewSemaError(new ErrorSema(line, inLine, SemaErrorEnum.REDEFINE, tips));
    }

    private OperationEnum operateLocate(String opString) {
        if (opString.equals("<=")) {
            return OperationEnum.LESS_EQUAL;
        } else if (opString.equals(">=")) {
            return OperationEnum.GREATER_EQUAL;
        } else if (opString.equals("<>")) {
            return OperationEnum.NOT_EQUAL;
        } else if (opString.equals("<")) {
            return OperationEnum.LESS;
        } else if (opString.equals(">")) {
            return OperationEnum.GREATER;
        } else if (opString.equals("=")) {
            return OperationEnum.EQUAL;
        }
        return null;
    }

    private LinkedList<VarElement> memoryAlign(HashMap<String, String> varTypeMap, HashMap<String, Integer> varSizeMap) {
        LinkedList<VarElement> sortedElementList = new LinkedList<>();
        for (String varName : varTypeMap.keySet()) {
            sortedElementList.add(new VarElement(varName, varTypeMap.get(varName), varSizeMap.get(varName)));
        }
        sortedElementList.sort(new Comparator<VarElement>() {
            @Override
            public int compare(VarElement o1, VarElement o2) {
                return o2.getVarSize() - o1.getVarSize();
            }
        });
        return sortedElementList;
    }
}
